You've already forked AstralRinth
forked from didirus/AstralRinth
fix: DI nonsense (#4174)
* fix: DI nonsense * fix: lint * fix: client try di issue * fix: injects outside of context * fix: use .catch * refactor: convert projects.vue to composition API. * fix: moderation checklist notif pos change watcher * fix: lint issues
This commit is contained in:
@@ -165,7 +165,14 @@ const handleOptionsClick = async (args) => {
|
|||||||
await navigator.clipboard.writeText(args.item.path)
|
await navigator.clipboard.writeText(args.item.path)
|
||||||
break
|
break
|
||||||
case 'install': {
|
case 'install': {
|
||||||
await installVersion(args.item.project_id, null, null, 'ProjectCardContextMenu')
|
await installVersion(
|
||||||
|
args.item.project_id,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
'ProjectCardContextMenu',
|
||||||
|
() => {},
|
||||||
|
() => {},
|
||||||
|
).catch(handleError)
|
||||||
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ const stop = async (e, context) => {
|
|||||||
const repair = async (e) => {
|
const repair = async (e) => {
|
||||||
e?.stopPropagation()
|
e?.stopPropagation()
|
||||||
|
|
||||||
await finish_install(props.instance)
|
await finish_install(props.instance).catch(handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
const openFolder = async () => {
|
const openFolder = async () => {
|
||||||
|
|||||||
@@ -118,7 +118,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { CheckIcon, DownloadIcon, HeartIcon, PlusIcon, TagsIcon } from '@modrinth/assets'
|
import { CheckIcon, DownloadIcon, HeartIcon, PlusIcon, TagsIcon } from '@modrinth/assets'
|
||||||
import { Avatar, ButtonStyled } from '@modrinth/ui'
|
import { Avatar, ButtonStyled, injectNotificationManager } from '@modrinth/ui'
|
||||||
import { formatCategory, formatNumber } from '@modrinth/utils'
|
import { formatCategory, formatNumber } from '@modrinth/utils'
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import relativeTime from 'dayjs/plugin/relativeTime'
|
import relativeTime from 'dayjs/plugin/relativeTime'
|
||||||
@@ -128,6 +128,8 @@ import { useRouter } from 'vue-router'
|
|||||||
import { install as installVersion } from '@/store/install.js'
|
import { install as installVersion } from '@/store/install.js'
|
||||||
dayjs.extend(relativeTime)
|
dayjs.extend(relativeTime)
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -175,7 +177,7 @@ async function install() {
|
|||||||
(profile) => {
|
(profile) => {
|
||||||
router.push(`/instance/${profile}`)
|
router.push(`/instance/${profile}`)
|
||||||
},
|
},
|
||||||
)
|
).catch(handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
const modpack = computed(() => props.project.project_type === 'modpack')
|
const modpack = computed(() => props.project.project_type === 'modpack')
|
||||||
|
|||||||
@@ -39,7 +39,14 @@ defineExpose({
|
|||||||
|
|
||||||
async function install() {
|
async function install() {
|
||||||
confirmModal.value.hide()
|
confirmModal.value.hide()
|
||||||
await installVersion(project.value.id, version.value.id, null, 'URLConfirmModal')
|
await installVersion(
|
||||||
|
project.value.id,
|
||||||
|
version.value.id,
|
||||||
|
null,
|
||||||
|
'URLConfirmModal',
|
||||||
|
() => {},
|
||||||
|
() => {},
|
||||||
|
).catch(handleError)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ async function install(instance) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await installMod(instance.path, version.id).catch(handleError)
|
await installMod(instance.path, version.id).catch(handleError)
|
||||||
await installVersionDependencies(instance, version)
|
await installVersionDependencies(instance, version).catch(handleError)
|
||||||
|
|
||||||
instance.installedMod = true
|
instance.installedMod = true
|
||||||
instance.installing = false
|
instance.installing = false
|
||||||
@@ -185,7 +185,7 @@ const createInstance = async () => {
|
|||||||
await router.push(`/instance/${encodeURIComponent(id)}/`)
|
await router.push(`/instance/${encodeURIComponent(id)}/`)
|
||||||
|
|
||||||
const instance = await get(id, true)
|
const instance = await get(id, true)
|
||||||
await installVersionDependencies(instance, versions.value[0])
|
await installVersionDependencies(instance, versions.value[0]).catch(handleError)
|
||||||
|
|
||||||
trackEvent('InstanceCreate', {
|
trackEvent('InstanceCreate', {
|
||||||
profile_name: name.value,
|
profile_name: name.value,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ const { formatMessage } = useVIntl()
|
|||||||
|
|
||||||
const props = defineProps<InstanceSettingsTabProps>()
|
const props = defineProps<InstanceSettingsTabProps>()
|
||||||
|
|
||||||
const globalSettings = (await get().catch(handleError)) as AppSettings
|
const globalSettings = (await get().catch(handleError)) as unknown as AppSettings
|
||||||
|
|
||||||
const overrideJavaInstall = ref(!!props.instance.java_path)
|
const overrideJavaInstall = ref(!!props.instance.java_path)
|
||||||
const optimalJava = readonly(await get_optimal_jre_key(props.instance.path).catch(handleError))
|
const optimalJava = readonly(await get_optimal_jre_key(props.instance.path).catch(handleError))
|
||||||
@@ -36,7 +36,10 @@ const envVars = ref(
|
|||||||
|
|
||||||
const overrideMemorySettings = ref(!!props.instance.memory)
|
const overrideMemorySettings = ref(!!props.instance.memory)
|
||||||
const memory = ref(props.instance.memory ?? globalSettings.memory)
|
const memory = ref(props.instance.memory ?? globalSettings.memory)
|
||||||
const { maxMemory, snapPoints } = await useMemorySlider()
|
const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) as unknown as {
|
||||||
|
maxMemory: number
|
||||||
|
snapPoints: number[]
|
||||||
|
}
|
||||||
|
|
||||||
const editProfileObject = computed(() => {
|
const editProfileObject = computed(() => {
|
||||||
const editProfile: {
|
const editProfile: {
|
||||||
|
|||||||
@@ -1,17 +1,22 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { Slider, Toggle } from '@modrinth/ui'
|
import { injectNotificationManager, Slider, Toggle } from '@modrinth/ui'
|
||||||
import { ref, watch } from 'vue'
|
import { ref, watch } from 'vue'
|
||||||
|
|
||||||
import useMemorySlider from '@/composables/useMemorySlider'
|
import useMemorySlider from '@/composables/useMemorySlider'
|
||||||
import { get, set } from '@/helpers/settings.ts'
|
import { get, set } from '@/helpers/settings.ts'
|
||||||
|
|
||||||
|
const { handleError } = injectNotificationManager()
|
||||||
|
|
||||||
const fetchSettings = await get()
|
const fetchSettings = await get()
|
||||||
fetchSettings.launchArgs = fetchSettings.extra_launch_args.join(' ')
|
fetchSettings.launchArgs = fetchSettings.extra_launch_args.join(' ')
|
||||||
fetchSettings.envVars = fetchSettings.custom_env_vars.map((x) => x.join('=')).join(' ')
|
fetchSettings.envVars = fetchSettings.custom_env_vars.map((x) => x.join('=')).join(' ')
|
||||||
|
|
||||||
const settings = ref(fetchSettings)
|
const settings = ref(fetchSettings)
|
||||||
|
|
||||||
const { maxMemory, snapPoints } = await useMemorySlider()
|
const { maxMemory, snapPoints } = (await useMemorySlider().catch(handleError)) as unknown as {
|
||||||
|
maxMemory: number
|
||||||
|
snapPoints: number[]
|
||||||
|
}
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
settings,
|
settings,
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
import { injectNotificationManager } from '@modrinth/ui'
|
|
||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import { get_max_memory } from '@/helpers/jre.js'
|
import { get_max_memory } from '@/helpers/jre.js'
|
||||||
|
|
||||||
export default async function () {
|
export default async function () {
|
||||||
const { handleError } = injectNotificationManager()
|
const maxMemory = ref(Math.floor((await get_max_memory()) / 1024))
|
||||||
const maxMemory = ref(Math.floor((await get_max_memory().catch(handleError)) / 1024))
|
|
||||||
|
|
||||||
const snapPoints = computed(() => {
|
const snapPoints = computed(() => {
|
||||||
let points = []
|
let points = []
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { injectNotificationManager } from '@modrinth/ui'
|
|
||||||
import { getVersion } from '@tauri-apps/api/app'
|
import { getVersion } from '@tauri-apps/api/app'
|
||||||
import { fetch } from '@tauri-apps/plugin-http'
|
import { fetch } from '@tauri-apps/plugin-http'
|
||||||
|
|
||||||
@@ -11,9 +10,9 @@ export const useFetch = async (url, item, isSilent) => {
|
|||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (!isSilent) {
|
if (!isSilent) {
|
||||||
const { handleError } = injectNotificationManager()
|
throw err
|
||||||
handleError({ message: `Error fetching ${item}` })
|
} else {
|
||||||
|
console.error(err)
|
||||||
}
|
}
|
||||||
console.error(err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* So, for example, addDefaultInstance creates a blank Profile object, where the Rust struct is serialized,
|
* So, for example, addDefaultInstance creates a blank Profile object, where the Rust struct is serialized,
|
||||||
* and deserialized into a usable JS object.
|
* and deserialized into a usable JS object.
|
||||||
*/
|
*/
|
||||||
import { injectNotificationManager } from '@modrinth/ui'
|
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
import { install_to_existing_profile } from '@/helpers/pack.js'
|
import { install_to_existing_profile } from '@/helpers/pack.js'
|
||||||
@@ -194,7 +193,6 @@ export async function edit_icon(path, iconPath) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function finish_install(instance) {
|
export async function finish_install(instance) {
|
||||||
const { handleError } = injectNotificationManager()
|
|
||||||
if (instance.install_stage !== 'pack_installed') {
|
if (instance.install_stage !== 'pack_installed') {
|
||||||
let linkedData = instance.linked_data
|
let linkedData = instance.linked_data
|
||||||
await install_to_existing_profile(
|
await install_to_existing_profile(
|
||||||
@@ -202,8 +200,8 @@ export async function finish_install(instance) {
|
|||||||
linkedData.version_id,
|
linkedData.version_id,
|
||||||
instance.name,
|
instance.name,
|
||||||
instance.path,
|
instance.path,
|
||||||
).catch(handleError)
|
)
|
||||||
} else {
|
} else {
|
||||||
await install(instance.path, false).catch(handleError)
|
await install(instance.path, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { injectNotificationManager } from '@modrinth/ui'
|
|
||||||
import { arrayBufferToBase64 } from '@modrinth/utils'
|
import { arrayBufferToBase64 } from '@modrinth/utils'
|
||||||
import { invoke } from '@tauri-apps/api/core'
|
import { invoke } from '@tauri-apps/api/core'
|
||||||
|
|
||||||
@@ -39,8 +38,7 @@ export const DEFAULT_MODELS: Record<string, SkinModel> = {
|
|||||||
|
|
||||||
export function filterSavedSkins(list: Skin[]) {
|
export function filterSavedSkins(list: Skin[]) {
|
||||||
const customSkins = list.filter((s) => s.source !== 'default')
|
const customSkins = list.filter((s) => s.source !== 'default')
|
||||||
const { handleError } = injectNotificationManager()
|
fixUnknownSkins(customSkins)
|
||||||
fixUnknownSkins(customSkins).catch(handleError)
|
|
||||||
return customSkins
|
return customSkins
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,7 +66,14 @@ const defaultCape = ref<Cape>()
|
|||||||
const originalSelectedSkin = ref<Skin | null>(null)
|
const originalSelectedSkin = ref<Skin | null>(null)
|
||||||
const originalDefaultCape = ref<Cape>()
|
const originalDefaultCape = ref<Cape>()
|
||||||
|
|
||||||
const savedSkins = computed(() => filterSavedSkins(skins.value))
|
const savedSkins = computed(() => {
|
||||||
|
try {
|
||||||
|
return filterSavedSkins(skins.value)
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error as Error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
})
|
||||||
const defaultSkins = computed(() => filterDefaultSkins(skins.value))
|
const defaultSkins = computed(() => filterDefaultSkins(skins.value))
|
||||||
|
|
||||||
const currentCape = computed(() => {
|
const currentCape = computed(() => {
|
||||||
|
|||||||
@@ -331,7 +331,7 @@ const stopInstance = async (context) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const repairInstance = async () => {
|
const repairInstance = async () => {
|
||||||
await finish_install(instance.value)
|
await finish_install(instance.value).catch(handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleRightClick = (event) => {
|
const handleRightClick = (event) => {
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ async function install(version) {
|
|||||||
(profile) => {
|
(profile) => {
|
||||||
router.push(`/instance/${profile}`)
|
router.push(`/instance/${profile}`)
|
||||||
},
|
},
|
||||||
)
|
).catch(handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
const options = ref(null)
|
const options = ref(null)
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import { injectNotificationManager } from '@modrinth/ui'
|
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { defineStore } from 'pinia'
|
import { defineStore } from 'pinia'
|
||||||
|
|
||||||
@@ -50,12 +49,11 @@ export const install = async (
|
|||||||
callback = () => {},
|
callback = () => {},
|
||||||
createInstanceCallback = () => {},
|
createInstanceCallback = () => {},
|
||||||
) => {
|
) => {
|
||||||
const { handleError } = injectNotificationManager()
|
const project = await get_project(projectId, 'must_revalidate')
|
||||||
const project = await get_project(projectId, 'must_revalidate').catch(handleError)
|
|
||||||
|
|
||||||
if (project.project_type === 'modpack') {
|
if (project.project_type === 'modpack') {
|
||||||
const version = versionId ?? project.versions[project.versions.length - 1]
|
const version = versionId ?? project.versions[project.versions.length - 1]
|
||||||
const packs = await list().catch(handleError)
|
const packs = await list()
|
||||||
|
|
||||||
if (packs.length === 0 || !packs.find((pack) => pack.linked_data?.project_id === project.id)) {
|
if (packs.length === 0 || !packs.find((pack) => pack.linked_data?.project_id === project.id)) {
|
||||||
await packInstall(
|
await packInstall(
|
||||||
@@ -64,7 +62,7 @@ export const install = async (
|
|||||||
project.title,
|
project.title,
|
||||||
project.icon_url,
|
project.icon_url,
|
||||||
createInstanceCallback,
|
createInstanceCallback,
|
||||||
).catch(handleError)
|
)
|
||||||
|
|
||||||
trackEvent('PackInstall', {
|
trackEvent('PackInstall', {
|
||||||
id: project.id,
|
id: project.id,
|
||||||
@@ -81,8 +79,8 @@ export const install = async (
|
|||||||
} else {
|
} else {
|
||||||
if (instancePath) {
|
if (instancePath) {
|
||||||
const [instance, instanceProjects, versions] = await Promise.all([
|
const [instance, instanceProjects, versions] = await Promise.all([
|
||||||
await get(instancePath).catch(handleError),
|
await get(instancePath),
|
||||||
await get_projects(instancePath).catch(handleError),
|
await get_projects(instancePath),
|
||||||
await get_version_many(project.versions, 'must_revalidate'),
|
await get_version_many(project.versions, 'must_revalidate'),
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -119,7 +117,7 @@ export const install = async (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await add_project_from_version(instance.path, version.id).catch(handleError)
|
await add_project_from_version(instance.path, version.id)
|
||||||
await installVersionDependencies(instance, version)
|
await installVersionDependencies(instance, version)
|
||||||
|
|
||||||
trackEvent('ProjectInstall', {
|
trackEvent('ProjectInstall', {
|
||||||
@@ -144,7 +142,7 @@ export const install = async (
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const versions = (await get_version_many(project.versions).catch(handleError)).sort(
|
const versions = (await get_version_many(project.versions)).sort(
|
||||||
(a, b) => dayjs(b.date_published) - dayjs(a.date_published),
|
(a, b) => dayjs(b.date_published) - dayjs(a.date_published),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -168,36 +166,27 @@ export const install = async (
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const installVersionDependencies = async (profile, version) => {
|
export const installVersionDependencies = async (profile, version) => {
|
||||||
const { handleError } = injectNotificationManager()
|
|
||||||
for (const dep of version.dependencies) {
|
for (const dep of version.dependencies) {
|
||||||
if (dep.dependency_type !== 'required') continue
|
if (dep.dependency_type !== 'required') continue
|
||||||
// disallow fabric api install on quilt
|
// disallow fabric api install on quilt
|
||||||
if (dep.project_id === 'P7dR8mSH' && profile.loader === 'quilt') continue
|
if (dep.project_id === 'P7dR8mSH' && profile.loader === 'quilt') continue
|
||||||
if (dep.version_id) {
|
if (dep.version_id) {
|
||||||
if (
|
if (dep.project_id && (await check_installed(profile.path, dep.project_id))) continue
|
||||||
dep.project_id &&
|
|
||||||
(await check_installed(profile.path, dep.project_id).catch(handleError))
|
|
||||||
)
|
|
||||||
continue
|
|
||||||
await add_project_from_version(profile.path, dep.version_id)
|
await add_project_from_version(profile.path, dep.version_id)
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (dep.project_id && (await check_installed(profile.path, dep.project_id))) continue
|
||||||
dep.project_id &&
|
|
||||||
(await check_installed(profile.path, dep.project_id).catch(handleError))
|
const depProject = await get_project(dep.project_id, 'must_revalidate')
|
||||||
|
|
||||||
|
const depVersions = (await get_version_many(depProject.versions, 'must_revalidate')).sort(
|
||||||
|
(a, b) => dayjs(b.date_published) - dayjs(a.date_published),
|
||||||
)
|
)
|
||||||
continue
|
|
||||||
|
|
||||||
const depProject = await get_project(dep.project_id, 'must_revalidate').catch(handleError)
|
|
||||||
|
|
||||||
const depVersions = (
|
|
||||||
await get_version_many(depProject.versions, 'must_revalidate').catch(handleError)
|
|
||||||
).sort((a, b) => dayjs(b.date_published) - dayjs(a.date_published))
|
|
||||||
|
|
||||||
const latest = depVersions.find(
|
const latest = depVersions.find(
|
||||||
(v) => v.game_versions.includes(profile.game_version) && v.loaders.includes(profile.loader),
|
(v) => v.game_versions.includes(profile.game_version) && v.loaders.includes(profile.loader),
|
||||||
)
|
)
|
||||||
if (latest) {
|
if (latest) {
|
||||||
await add_project_from_version(profile.path, latest.id).catch(handleError)
|
await add_project_from_version(profile.path, latest.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -397,7 +397,8 @@ import { useModerationStore } from '~/store/moderation.ts'
|
|||||||
import KeybindsModal from './ChecklistKeybindsModal.vue'
|
import KeybindsModal from './ChecklistKeybindsModal.vue'
|
||||||
import ModpackPermissionsFlow from './ModpackPermissionsFlow.vue'
|
import ModpackPermissionsFlow from './ModpackPermissionsFlow.vue'
|
||||||
|
|
||||||
const { addNotification } = injectNotificationManager()
|
const notifications = injectNotificationManager()
|
||||||
|
const { addNotification } = notifications
|
||||||
|
|
||||||
const keybindsModal = ref<InstanceType<typeof KeybindsModal>>()
|
const keybindsModal = ref<InstanceType<typeof KeybindsModal>>()
|
||||||
|
|
||||||
@@ -626,6 +627,11 @@ function handleKeybinds(event: KeyboardEvent) {
|
|||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
window.addEventListener('keydown', handleKeybinds)
|
window.addEventListener('keydown', handleKeybinds)
|
||||||
initializeAllStages()
|
initializeAllStages()
|
||||||
|
notifications.setNotificationLocation('left')
|
||||||
|
})
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
notifications.setNotificationLocation('right')
|
||||||
})
|
})
|
||||||
|
|
||||||
function initializeAllStages() {
|
function initializeAllStages() {
|
||||||
|
|||||||
@@ -74,12 +74,14 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { DownloadIcon, ExternalIcon, SpinnerIcon, XIcon } from '@modrinth/assets'
|
import { DownloadIcon, ExternalIcon, SpinnerIcon, XIcon } from '@modrinth/assets'
|
||||||
import { BackupWarning, ButtonStyled, NewModal } from '@modrinth/ui'
|
import { BackupWarning, ButtonStyled, injectNotificationManager, NewModal } from '@modrinth/ui'
|
||||||
import { ModrinthServersFetchError } from '@modrinth/utils'
|
import { ModrinthServersFetchError } from '@modrinth/utils'
|
||||||
import { computed, nextTick, ref } from 'vue'
|
import { computed, nextTick, ref } from 'vue'
|
||||||
|
|
||||||
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'
|
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'
|
||||||
import { handleError } from '~/composables/servers/modrinth-servers.ts'
|
import { handleServersError } from '~/composables/servers/modrinth-servers.ts'
|
||||||
|
|
||||||
|
const notifications = injectNotificationManager()
|
||||||
|
|
||||||
const cf = ref(false)
|
const cf = ref(false)
|
||||||
|
|
||||||
@@ -120,18 +122,19 @@ const handleSubmit = async () => {
|
|||||||
hide()
|
hide()
|
||||||
} else {
|
} else {
|
||||||
submitted.value = false
|
submitted.value = false
|
||||||
handleError(
|
handleServersError(
|
||||||
new ModrinthServersFetchError(
|
new ModrinthServersFetchError(
|
||||||
'Could not find CurseForge modpack at that URL.',
|
'Could not find CurseForge modpack at that URL.',
|
||||||
404,
|
404,
|
||||||
new Error(`No modpack found at ${url.value}`),
|
new Error(`No modpack found at ${url.value}`),
|
||||||
),
|
),
|
||||||
|
notifications,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
submitted.value = false
|
submitted.value = false
|
||||||
console.error('Error installing:', error)
|
console.error('Error installing:', error)
|
||||||
handleError(error)
|
handleServersError(error, notifications)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { injectNotificationManager } from '@modrinth/ui'
|
|
||||||
|
|
||||||
export const useAuth = async (oldToken = null) => {
|
export const useAuth = async (oldToken = null) => {
|
||||||
const auth = useState('auth', () => ({
|
const auth = useState('auth', () => ({
|
||||||
user: null,
|
user: null,
|
||||||
@@ -119,23 +117,17 @@ export const getAuthUrl = (provider, redirect = '/dashboard') => {
|
|||||||
|
|
||||||
export const removeAuthProvider = async (provider) => {
|
export const removeAuthProvider = async (provider) => {
|
||||||
startLoading()
|
startLoading()
|
||||||
try {
|
|
||||||
const auth = await useAuth()
|
|
||||||
|
|
||||||
await useBaseFetch('auth/provider', {
|
const auth = await useAuth()
|
||||||
method: 'DELETE',
|
|
||||||
body: {
|
await useBaseFetch('auth/provider', {
|
||||||
provider,
|
method: 'DELETE',
|
||||||
},
|
body: {
|
||||||
})
|
provider,
|
||||||
await useAuth(auth.value.token)
|
},
|
||||||
} catch (err) {
|
})
|
||||||
const { addNotification } = injectNotificationManager()
|
|
||||||
addNotification({
|
await useAuth(auth.value.token)
|
||||||
title: 'An error occurred',
|
|
||||||
text: err.data.description,
|
|
||||||
type: 'error',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
stopLoading()
|
stopLoading()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { injectNotificationManager } from '@modrinth/ui'
|
import type { AbstractWebNotificationManager } from '@modrinth/ui'
|
||||||
import type { JWTAuth, ModuleError, ModuleName } from '@modrinth/utils'
|
import type { JWTAuth, ModuleError, ModuleName } from '@modrinth/utils'
|
||||||
import { ModrinthServerError } from '@modrinth/utils'
|
import { ModrinthServerError } from '@modrinth/utils'
|
||||||
|
|
||||||
@@ -13,17 +13,16 @@ import {
|
|||||||
} from './modules/index.ts'
|
} from './modules/index.ts'
|
||||||
import { useServersFetch } from './servers-fetch.ts'
|
import { useServersFetch } from './servers-fetch.ts'
|
||||||
|
|
||||||
export function handleError(err: any) {
|
export function handleServersError(err: any, notifications: AbstractWebNotificationManager) {
|
||||||
const { addNotification } = injectNotificationManager()
|
|
||||||
if (err instanceof ModrinthServerError && err.v1Error) {
|
if (err instanceof ModrinthServerError && err.v1Error) {
|
||||||
addNotification({
|
notifications.addNotification({
|
||||||
title: err.v1Error?.context ?? `An error occurred`,
|
title: err.v1Error?.context ?? `An error occurred`,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: err.v1Error.description,
|
text: err.v1Error.description,
|
||||||
errorCode: err.v1Error.error,
|
errorCode: err.v1Error.error,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
addNotification({
|
notifications.addNotification({
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
type: 'error',
|
type: 'error',
|
||||||
text: err.message ?? (err.data ? err.data.description : err),
|
text: err.message ?? (err.data ? err.data.description : err),
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
import type { AbstractWebNotificationManager } from '@modrinth/ui'
|
||||||
import { injectNotificationManager } from '@modrinth/ui'
|
import { injectNotificationManager } from '@modrinth/ui'
|
||||||
|
|
||||||
type AsyncFunction<TArgs extends any[], TResult> = (...args: TArgs) => Promise<TResult>
|
type AsyncFunction<TArgs extends any[], TResult> = (...args: TArgs) => Promise<TResult>
|
||||||
type ErrorFunction = (err: any) => void | Promise<void>
|
type ErrorFunction = (
|
||||||
|
err: any,
|
||||||
|
addNotification: typeof AbstractWebNotificationManager.prototype.addNotification,
|
||||||
|
) => void | Promise<void>
|
||||||
type VoidFunction = () => void | Promise<void>
|
type VoidFunction = () => void | Promise<void>
|
||||||
|
|
||||||
type useClientTry = <TArgs extends any[], TResult>(
|
type useClientTry = <TArgs extends any[], TResult>(
|
||||||
@@ -10,8 +14,7 @@ type useClientTry = <TArgs extends any[], TResult>(
|
|||||||
onFinish?: VoidFunction,
|
onFinish?: VoidFunction,
|
||||||
) => (...args: TArgs) => Promise<TResult | undefined>
|
) => (...args: TArgs) => Promise<TResult | undefined>
|
||||||
|
|
||||||
const defaultOnError: ErrorFunction = (error) => {
|
const defaultOnError: ErrorFunction = (error, addNotification) => {
|
||||||
const { addNotification } = injectNotificationManager()
|
|
||||||
addNotification({
|
addNotification({
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
text: error?.data?.description || error.message || error || 'Unknown error',
|
text: error?.data?.description || error.message || error || 'Unknown error',
|
||||||
@@ -19,15 +22,15 @@ const defaultOnError: ErrorFunction = (error) => {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useClientTry: useClientTry =
|
export const useClientTry: useClientTry = (fn, onFail = defaultOnError, onFinish) => {
|
||||||
(fn, onFail = defaultOnError, onFinish) =>
|
const { addNotification } = injectNotificationManager()
|
||||||
async (...args) => {
|
return async (...args) => {
|
||||||
startLoading()
|
startLoading()
|
||||||
try {
|
try {
|
||||||
return await fn(...args)
|
return await fn(...args)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (onFail) {
|
if (onFail) {
|
||||||
await onFail(err)
|
await onFail(err, addNotification)
|
||||||
} else {
|
} else {
|
||||||
console.error('[CLIENT TRY ERROR]', err)
|
console.error('[CLIENT TRY ERROR]', err)
|
||||||
}
|
}
|
||||||
@@ -36,3 +39,4 @@ export const useClientTry: useClientTry =
|
|||||||
stopLoading()
|
stopLoading()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -137,28 +137,10 @@ export const userFollowProject = async (project) => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const resendVerifyEmail = async () => {
|
export const resendVerifyEmail = async () => {
|
||||||
// const { injectNotificationManager } = await import("@modrinth/ui");
|
await useBaseFetch('auth/email/resend_verify', {
|
||||||
// const { addNotification } = injectNotificationManager();
|
method: 'POST',
|
||||||
|
})
|
||||||
startLoading()
|
await useAuth()
|
||||||
try {
|
|
||||||
await useBaseFetch('auth/email/resend_verify', {
|
|
||||||
method: 'POST',
|
|
||||||
})
|
|
||||||
|
|
||||||
const auth = await useAuth()
|
|
||||||
addNotification({
|
|
||||||
title: 'Email sent',
|
|
||||||
text: `An email with a link to verify your account has been sent to ${auth.value.user.email}.`,
|
|
||||||
type: 'success',
|
|
||||||
})
|
|
||||||
} catch (err) {
|
|
||||||
addNotification({
|
|
||||||
title: 'An error occurred',
|
|
||||||
text: err.data.description,
|
|
||||||
type: 'error',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
stopLoading()
|
stopLoading()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
<template #actions>
|
<template #actions>
|
||||||
<button v-if="auth?.user?.email" class="btn" @click="resendVerifyEmail">
|
<button v-if="auth?.user?.email" class="btn" @click="handleResendEmailVerification">
|
||||||
{{ formatMessage(verifyEmailBannerMessages.action) }}
|
{{ formatMessage(verifyEmailBannerMessages.action) }}
|
||||||
</button>
|
</button>
|
||||||
<nuxt-link v-else class="btn" to="/settings/account">
|
<nuxt-link v-else class="btn" to="/settings/account">
|
||||||
@@ -854,6 +854,23 @@ const footerMessages = defineMessages({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
async function handleResendEmailVerification() {
|
||||||
|
try {
|
||||||
|
await resendVerifyEmail()
|
||||||
|
addNotification({
|
||||||
|
title: 'Email sent',
|
||||||
|
text: `An email with a link to verify your account has been sent to ${auth.value.user.email}.`,
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
addNotification({
|
||||||
|
title: 'An error occurred',
|
||||||
|
text: err.data.description,
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
link: [
|
link: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1575,18 +1575,6 @@ const showModerationChecklist = useLocalStorage(
|
|||||||
)
|
)
|
||||||
const collapsedModerationChecklist = useLocalStorage('collapsed-moderation-checklist', false)
|
const collapsedModerationChecklist = useLocalStorage('collapsed-moderation-checklist', false)
|
||||||
|
|
||||||
watch(
|
|
||||||
showModerationChecklist,
|
|
||||||
(newValue) => {
|
|
||||||
notifications.setNotificationLocation(newValue ? 'left' : 'right')
|
|
||||||
},
|
|
||||||
{ immediate: true },
|
|
||||||
)
|
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
notifications.setNotificationLocation('right')
|
|
||||||
})
|
|
||||||
|
|
||||||
if (import.meta.client && history && history.state && history.state.showChecklist) {
|
if (import.meta.client && history && history.state && history.state.showChecklist) {
|
||||||
showModerationChecklist.value = true
|
showModerationChecklist.value = true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -335,6 +335,13 @@ useSeoMeta({
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
export default defineNuxtComponent({
|
export default defineNuxtComponent({
|
||||||
|
setup() {
|
||||||
|
const { addNotification } = injectNotificationManager()
|
||||||
|
|
||||||
|
return {
|
||||||
|
addNotification,
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
expandedGalleryItem: null,
|
expandedGalleryItem: null,
|
||||||
@@ -425,8 +432,6 @@ export default defineNuxtComponent({
|
|||||||
this.shouldPreventActions = true
|
this.shouldPreventActions = true
|
||||||
startLoading()
|
startLoading()
|
||||||
|
|
||||||
const { addNotification } = injectNotificationManager()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let url = `project/${this.project.id}/gallery?ext=${
|
let url = `project/${this.project.id}/gallery?ext=${
|
||||||
this.editFile
|
this.editFile
|
||||||
@@ -452,7 +457,7 @@ export default defineNuxtComponent({
|
|||||||
|
|
||||||
this.$refs.modal_edit_item.hide()
|
this.$refs.modal_edit_item.hide()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
addNotification({
|
this.addNotification({
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
text: err.data ? err.data.description : err,
|
text: err.data ? err.data.description : err,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -465,9 +470,6 @@ export default defineNuxtComponent({
|
|||||||
async editGalleryItem() {
|
async editGalleryItem() {
|
||||||
this.shouldPreventActions = true
|
this.shouldPreventActions = true
|
||||||
startLoading()
|
startLoading()
|
||||||
|
|
||||||
const { addNotification } = injectNotificationManager()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
let url = `project/${this.project.id}/gallery?url=${encodeURIComponent(
|
let url = `project/${this.project.id}/gallery?url=${encodeURIComponent(
|
||||||
this.project.gallery[this.editIndex].url,
|
this.project.gallery[this.editIndex].url,
|
||||||
@@ -490,7 +492,7 @@ export default defineNuxtComponent({
|
|||||||
await this.resetProject()
|
await this.resetProject()
|
||||||
this.$refs.modal_edit_item.hide()
|
this.$refs.modal_edit_item.hide()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
addNotification({
|
this.addNotification({
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
text: err.data ? err.data.description : err,
|
text: err.data ? err.data.description : err,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -503,8 +505,6 @@ export default defineNuxtComponent({
|
|||||||
async deleteGalleryImage() {
|
async deleteGalleryImage() {
|
||||||
startLoading()
|
startLoading()
|
||||||
|
|
||||||
const { addNotification } = injectNotificationManager()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await useBaseFetch(
|
await useBaseFetch(
|
||||||
`project/${this.project.id}/gallery?url=${encodeURIComponent(
|
`project/${this.project.id}/gallery?url=${encodeURIComponent(
|
||||||
@@ -517,7 +517,7 @@ export default defineNuxtComponent({
|
|||||||
|
|
||||||
await this.resetProject()
|
await this.resetProject()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
addNotification({
|
this.addNotification({
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
text: err.data ? err.data.description : err,
|
text: err.data ? err.data.description : err,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
|
|||||||
@@ -750,6 +750,8 @@ export default defineNuxtComponent({
|
|||||||
const data = useNuxtApp()
|
const data = useNuxtApp()
|
||||||
const route = useNativeRoute()
|
const route = useNativeRoute()
|
||||||
|
|
||||||
|
const { addNotification } = injectNotificationManager()
|
||||||
|
|
||||||
const auth = await useAuth()
|
const auth = await useAuth()
|
||||||
const tags = useTags()
|
const tags = useTags()
|
||||||
const flags = useFeatureFlags()
|
const flags = useFeatureFlags()
|
||||||
@@ -915,6 +917,7 @@ export default defineNuxtComponent({
|
|||||||
alternateFile: ref(alternateFile),
|
alternateFile: ref(alternateFile),
|
||||||
replaceFile: ref(replaceFile),
|
replaceFile: ref(replaceFile),
|
||||||
uploadedImageIds: ref([]),
|
uploadedImageIds: ref([]),
|
||||||
|
addNotification,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@@ -996,8 +999,7 @@ export default defineNuxtComponent({
|
|||||||
const project = await useBaseFetch(`project/${newDependencyId}`)
|
const project = await useBaseFetch(`project/${newDependencyId}`)
|
||||||
|
|
||||||
if (this.version.dependencies.some((dep) => project.id === dep.project_id)) {
|
if (this.version.dependencies.some((dep) => project.id === dep.project_id)) {
|
||||||
const { addNotification } = injectNotificationManager()
|
this.addNotification({
|
||||||
addNotification({
|
|
||||||
title: 'Dependency already added',
|
title: 'Dependency already added',
|
||||||
text: 'You cannot add the same dependency twice.',
|
text: 'You cannot add the same dependency twice.',
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -1021,8 +1023,7 @@ export default defineNuxtComponent({
|
|||||||
const project = await useBaseFetch(`project/${version.project_id}`)
|
const project = await useBaseFetch(`project/${version.project_id}`)
|
||||||
|
|
||||||
if (this.version.dependencies.some((dep) => version.id === dep.version_id)) {
|
if (this.version.dependencies.some((dep) => version.id === dep.version_id)) {
|
||||||
const { addNotification } = injectNotificationManager()
|
this.addNotification({
|
||||||
addNotification({
|
|
||||||
title: 'Dependency already added',
|
title: 'Dependency already added',
|
||||||
text: 'You cannot add the same dependency twice.',
|
text: 'You cannot add the same dependency twice.',
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -1049,8 +1050,7 @@ export default defineNuxtComponent({
|
|||||||
this.newDependencyId = ''
|
this.newDependencyId = ''
|
||||||
} catch {
|
} catch {
|
||||||
if (!hideErrors) {
|
if (!hideErrors) {
|
||||||
const { addNotification } = injectNotificationManager()
|
this.addNotification({
|
||||||
addNotification({
|
|
||||||
title: 'Invalid Dependency',
|
title: 'Invalid Dependency',
|
||||||
text: 'The specified dependency could not be found',
|
text: 'The specified dependency could not be found',
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -1143,8 +1143,7 @@ export default defineNuxtComponent({
|
|||||||
)}`,
|
)}`,
|
||||||
)
|
)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const { addNotification } = injectNotificationManager()
|
this.addNotification({
|
||||||
addNotification({
|
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
text: err.data ? err.data.description : err,
|
text: err.data ? err.data.description : err,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -1168,8 +1167,7 @@ export default defineNuxtComponent({
|
|||||||
try {
|
try {
|
||||||
await this.createVersionRaw(this.version)
|
await this.createVersionRaw(this.version)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const { addNotification } = injectNotificationManager()
|
this.addNotification({
|
||||||
addNotification({
|
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
text: err.data ? err.data.description : err,
|
text: err.data ? err.data.description : err,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
@@ -1292,15 +1290,13 @@ export default defineNuxtComponent({
|
|||||||
|
|
||||||
this.$refs.modal_package_mod.hide()
|
this.$refs.modal_package_mod.hide()
|
||||||
|
|
||||||
const { addNotification } = injectNotificationManager()
|
this.addNotification({
|
||||||
addNotification({
|
|
||||||
title: 'Packaging Success',
|
title: 'Packaging Success',
|
||||||
text: 'Your data pack was successfully packaged as a mod! Make sure to playtest to check for errors.',
|
text: 'Your data pack was successfully packaged as a mod! Make sure to playtest to check for errors.',
|
||||||
type: 'success',
|
type: 'success',
|
||||||
})
|
})
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const { addNotification } = injectNotificationManager()
|
this.addNotification({
|
||||||
addNotification({
|
|
||||||
title: 'An error occurred',
|
title: 'An error occurred',
|
||||||
text: err.data ? err.data.description : err,
|
text: err.data ? err.data.description : err,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
|
|||||||
@@ -40,7 +40,11 @@
|
|||||||
</template>
|
</template>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<button v-if="auth.user" class="btn btn-primary continue-btn" @click="resendVerifyEmail">
|
<button
|
||||||
|
v-if="auth.user"
|
||||||
|
class="btn btn-primary continue-btn"
|
||||||
|
@click="handleResendEmailVerification"
|
||||||
|
>
|
||||||
{{ formatMessage(failedVerificationMessages.action) }} <RightArrowIcon />
|
{{ formatMessage(failedVerificationMessages.action) }} <RightArrowIcon />
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@@ -53,7 +57,9 @@
|
|||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { RightArrowIcon, SettingsIcon } from '@modrinth/assets'
|
import { RightArrowIcon, SettingsIcon } from '@modrinth/assets'
|
||||||
|
import { injectNotificationManager } from '@modrinth/ui'
|
||||||
|
|
||||||
|
const { addNotification } = injectNotificationManager()
|
||||||
const { formatMessage } = useVIntl()
|
const { formatMessage } = useVIntl()
|
||||||
|
|
||||||
const messages = defineMessages({
|
const messages = defineMessages({
|
||||||
@@ -149,4 +155,21 @@ if (route.query.flow) {
|
|||||||
success.value = false
|
success.value = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleResendEmailVerification() {
|
||||||
|
try {
|
||||||
|
await resendVerifyEmail()
|
||||||
|
addNotification({
|
||||||
|
title: 'Email sent',
|
||||||
|
text: `An email with a link to verify your account has been sent to ${auth.value.user.email}.`,
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
} catch (err) {
|
||||||
|
addNotification({
|
||||||
|
title: 'An error occurred',
|
||||||
|
text: err.data.description,
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -300,7 +300,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
EditIcon,
|
EditIcon,
|
||||||
IssuesIcon,
|
IssuesIcon,
|
||||||
@@ -328,170 +328,116 @@ import Modal from '~/components/ui/Modal.vue'
|
|||||||
import ModalCreation from '~/components/ui/ModalCreation.vue'
|
import ModalCreation from '~/components/ui/ModalCreation.vue'
|
||||||
import { getProjectTypeForUrl } from '~/helpers/projects.js'
|
import { getProjectTypeForUrl } from '~/helpers/projects.js'
|
||||||
|
|
||||||
export default defineNuxtComponent({
|
useHead({ title: 'Projects - Modrinth' })
|
||||||
components: {
|
|
||||||
Avatar,
|
|
||||||
ButtonStyled,
|
|
||||||
ProjectStatusBadge,
|
|
||||||
SettingsIcon,
|
|
||||||
TrashIcon,
|
|
||||||
Checkbox,
|
|
||||||
IssuesIcon,
|
|
||||||
PlusIcon,
|
|
||||||
XIcon,
|
|
||||||
EditIcon,
|
|
||||||
SaveIcon,
|
|
||||||
Modal,
|
|
||||||
ModalCreation,
|
|
||||||
Multiselect,
|
|
||||||
CopyCode,
|
|
||||||
SortAscIcon,
|
|
||||||
SortDescIcon,
|
|
||||||
},
|
|
||||||
async setup() {
|
|
||||||
const { formatMessage } = useVIntl()
|
|
||||||
|
|
||||||
const user = await useUser()
|
// const UPLOAD_VERSION = 1 << 0
|
||||||
await initUserProjects()
|
// const DELETE_VERSION = 1 << 1
|
||||||
return { formatMessage, user: ref(user) }
|
const EDIT_DETAILS = 1 << 2
|
||||||
},
|
// const EDIT_BODY = 1 << 3
|
||||||
data() {
|
// const MANAGE_INVITES = 1 << 4
|
||||||
return {
|
// const REMOVE_MEMBER = 1 << 5
|
||||||
projects: this.updateSort(this.user.projects, 'Name'),
|
// const EDIT_MEMBER = 1 << 6
|
||||||
versions: [],
|
// const DELETE_PROJECT = 1 << 7
|
||||||
selectedProjects: [],
|
|
||||||
sortBy: 'Name',
|
|
||||||
descending: false,
|
|
||||||
editLinks: {
|
|
||||||
showAffected: false,
|
|
||||||
source: {
|
|
||||||
val: '',
|
|
||||||
clear: false,
|
|
||||||
},
|
|
||||||
discord: {
|
|
||||||
val: '',
|
|
||||||
clear: false,
|
|
||||||
},
|
|
||||||
wiki: {
|
|
||||||
val: '',
|
|
||||||
clear: false,
|
|
||||||
},
|
|
||||||
issues: {
|
|
||||||
val: '',
|
|
||||||
clear: false,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
commonMessages,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
head: {
|
|
||||||
title: 'Projects - Modrinth',
|
|
||||||
},
|
|
||||||
created() {
|
|
||||||
this.UPLOAD_VERSION = 1 << 0
|
|
||||||
this.DELETE_VERSION = 1 << 1
|
|
||||||
this.EDIT_DETAILS = 1 << 2
|
|
||||||
this.EDIT_BODY = 1 << 3
|
|
||||||
this.MANAGE_INVITES = 1 << 4
|
|
||||||
this.REMOVE_MEMBER = 1 << 5
|
|
||||||
this.EDIT_MEMBER = 1 << 6
|
|
||||||
this.DELETE_PROJECT = 1 << 7
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getProjectTypeForUrl,
|
|
||||||
formatProjectType,
|
|
||||||
updateDescending() {
|
|
||||||
this.descending = !this.descending
|
|
||||||
this.projects = this.updateSort(this.projects, this.sortBy, this.descending)
|
|
||||||
},
|
|
||||||
updateSort(projects, sort, descending) {
|
|
||||||
let sortedArray = projects
|
|
||||||
switch (sort) {
|
|
||||||
case 'Name':
|
|
||||||
sortedArray = projects.slice().sort((a, b) => {
|
|
||||||
return a.title.localeCompare(b.title)
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'Status':
|
|
||||||
sortedArray = projects.slice().sort((a, b) => {
|
|
||||||
if (a.status < b.status) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if (a.status > b.status) {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
break
|
|
||||||
case 'Type':
|
|
||||||
sortedArray = projects.slice().sort((a, b) => {
|
|
||||||
if (a.project_type < b.project_type) {
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
if (a.project_type > b.project_type) {
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
})
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descending) {
|
const { addNotification } = injectNotificationManager()
|
||||||
sortedArray = sortedArray.reverse()
|
const { formatMessage } = useVIntl()
|
||||||
}
|
|
||||||
|
|
||||||
return sortedArray
|
const user = await useUser()
|
||||||
},
|
const projects = ref([])
|
||||||
async bulkEditLinks() {
|
const selectedProjects = ref([])
|
||||||
const { addNotification } = injectNotificationManager()
|
const sortBy = ref('Name')
|
||||||
|
const descending = ref(false)
|
||||||
try {
|
const editLinks = reactive({
|
||||||
const baseData = {
|
showAffected: false,
|
||||||
issues_url: this.editLinks.issues.clear ? null : this.editLinks.issues.val.trim(),
|
source: { val: '', clear: false },
|
||||||
source_url: this.editLinks.source.clear ? null : this.editLinks.source.val.trim(),
|
discord: { val: '', clear: false },
|
||||||
wiki_url: this.editLinks.wiki.clear ? null : this.editLinks.wiki.val.trim(),
|
wiki: { val: '', clear: false },
|
||||||
discord_url: this.editLinks.discord.clear ? null : this.editLinks.discord.val.trim(),
|
issues: { val: '', clear: false },
|
||||||
}
|
|
||||||
const filteredData = Object.fromEntries(
|
|
||||||
Object.entries(baseData).filter(([, v]) => v !== ''),
|
|
||||||
)
|
|
||||||
|
|
||||||
await useBaseFetch(
|
|
||||||
`projects?ids=${JSON.stringify(this.selectedProjects.map((x) => x.id))}`,
|
|
||||||
{
|
|
||||||
method: 'PATCH',
|
|
||||||
body: filteredData,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
this.$refs.editLinksModal.hide()
|
|
||||||
addNotification({
|
|
||||||
title: 'Success',
|
|
||||||
text: "Bulk edited selected project's links.",
|
|
||||||
type: 'success',
|
|
||||||
})
|
|
||||||
this.selectedProjects = []
|
|
||||||
|
|
||||||
this.editLinks.issues.val = ''
|
|
||||||
this.editLinks.source.val = ''
|
|
||||||
this.editLinks.wiki.val = ''
|
|
||||||
this.editLinks.discord.val = ''
|
|
||||||
this.editLinks.issues.clear = false
|
|
||||||
this.editLinks.source.clear = false
|
|
||||||
this.editLinks.wiki.clear = false
|
|
||||||
this.editLinks.discord.clear = false
|
|
||||||
} catch (e) {
|
|
||||||
addNotification({
|
|
||||||
title: 'An error occurred',
|
|
||||||
text: e,
|
|
||||||
type: 'error',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const editLinksModal = ref(null)
|
||||||
|
const modal_creation = ref(null)
|
||||||
|
|
||||||
|
function updateSort(list, sort, desc) {
|
||||||
|
let sortedArray = list
|
||||||
|
switch (sort) {
|
||||||
|
case 'Name':
|
||||||
|
sortedArray = list.slice().sort((a, b) => a.title.localeCompare(b.title))
|
||||||
|
break
|
||||||
|
case 'Status':
|
||||||
|
sortedArray = list.slice().sort((a, b) => {
|
||||||
|
if (a.status < b.status) return -1
|
||||||
|
if (a.status > b.status) return 1
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
break
|
||||||
|
case 'Type':
|
||||||
|
sortedArray = list.slice().sort((a, b) => {
|
||||||
|
if (a.project_type < b.project_type) return -1
|
||||||
|
if (a.project_type > b.project_type) return 1
|
||||||
|
return 0
|
||||||
|
})
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (desc) sortedArray = sortedArray.reverse()
|
||||||
|
return sortedArray
|
||||||
|
}
|
||||||
|
|
||||||
|
function resort() {
|
||||||
|
projects.value = updateSort(projects.value, sortBy.value, descending.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateDescending() {
|
||||||
|
descending.value = !descending.value
|
||||||
|
resort()
|
||||||
|
}
|
||||||
|
|
||||||
|
async function bulkEditLinks() {
|
||||||
|
try {
|
||||||
|
const baseData = {
|
||||||
|
issues_url: editLinks.issues.clear ? null : editLinks.issues.val.trim(),
|
||||||
|
source_url: editLinks.source.clear ? null : editLinks.source.val.trim(),
|
||||||
|
wiki_url: editLinks.wiki.clear ? null : editLinks.wiki.val.trim(),
|
||||||
|
discord_url: editLinks.discord.clear ? null : editLinks.discord.val.trim(),
|
||||||
|
}
|
||||||
|
const filteredData = Object.fromEntries(Object.entries(baseData).filter(([, v]) => v !== ''))
|
||||||
|
|
||||||
|
await useBaseFetch(`projects?ids=${JSON.stringify(selectedProjects.value.map((x) => x.id))}`, {
|
||||||
|
method: 'PATCH',
|
||||||
|
body: filteredData,
|
||||||
|
})
|
||||||
|
|
||||||
|
editLinksModal.value?.hide()
|
||||||
|
addNotification({
|
||||||
|
title: 'Success',
|
||||||
|
text: "Bulk edited selected project's links.",
|
||||||
|
type: 'success',
|
||||||
|
})
|
||||||
|
selectedProjects.value = []
|
||||||
|
|
||||||
|
editLinks.issues.val = ''
|
||||||
|
editLinks.source.val = ''
|
||||||
|
editLinks.wiki.val = ''
|
||||||
|
editLinks.discord.val = ''
|
||||||
|
editLinks.issues.clear = false
|
||||||
|
editLinks.source.clear = false
|
||||||
|
editLinks.wiki.clear = false
|
||||||
|
editLinks.discord.clear = false
|
||||||
|
} catch (e) {
|
||||||
|
addNotification({
|
||||||
|
title: 'An error occurred',
|
||||||
|
text: e,
|
||||||
|
type: 'error',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await initUserProjects()
|
||||||
|
if (user.value?.projects) {
|
||||||
|
projects.value = updateSort(user.value.projects, 'Name', false)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.grid-table {
|
.grid-table {
|
||||||
|
|||||||
@@ -101,7 +101,7 @@
|
|||||||
email
|
email
|
||||||
{{ auth.user.payout_data.paypal_address }}
|
{{ auth.user.payout_data.paypal_address }}
|
||||||
</p>
|
</p>
|
||||||
<button class="btn mt-4" @click="removeAuthProvider('paypal')">
|
<button class="btn mt-4" @click="handleRemoveAuthProvider('paypal')">
|
||||||
<XIcon />
|
<XIcon />
|
||||||
Disconnect account
|
Disconnect account
|
||||||
</button>
|
</button>
|
||||||
@@ -154,7 +154,9 @@ import { formatDate } from '@modrinth/utils'
|
|||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const { addNotification } = injectNotificationManager()
|
import { removeAuthProvider } from '~/composables/auth.js'
|
||||||
|
|
||||||
|
const { addNotification, handleError } = injectNotificationManager()
|
||||||
const auth = await useAuth()
|
const auth = await useAuth()
|
||||||
const minWithdraw = ref(0.01)
|
const minWithdraw = ref(0.01)
|
||||||
|
|
||||||
@@ -170,6 +172,14 @@ const deadlineEnding = computed(() => {
|
|||||||
return deadline
|
return deadline
|
||||||
})
|
})
|
||||||
|
|
||||||
|
async function handleRemoveAuthProvider(provider) {
|
||||||
|
try {
|
||||||
|
await removeAuthProvider(provider)
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const availableSoonDates = computed(() => {
|
const availableSoonDates = computed(() => {
|
||||||
// Get the next 3 dates from userBalance.dates that are from now to the deadline + 4 months to make sure we get all the pending ones.
|
// Get the next 3 dates from userBalance.dates that are from now to the deadline + 4 months to make sure we get all the pending ones.
|
||||||
const dates = Object.keys(userBalance.value.dates)
|
const dates = Object.keys(userBalance.value.dates)
|
||||||
|
|||||||
@@ -62,10 +62,13 @@ const showPreviewImage = (files) => {
|
|||||||
const orgId = useRouteId()
|
const orgId = useRouteId()
|
||||||
|
|
||||||
const onSaveChanges = useClientTry(async () => {
|
const onSaveChanges = useClientTry(async () => {
|
||||||
if (hasChanges.value) {
|
// Only PATCH organization details if there are actual field changes
|
||||||
await patchOrganization(orgId, patchData.value)
|
const hasOrgFieldChanges = Object.keys(patchData.value).length > 0
|
||||||
|
if (hasOrgFieldChanges) {
|
||||||
|
await patchOrganization(patchData.value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle icon deletion / upload separately
|
||||||
if (deletedIcon.value) {
|
if (deletedIcon.value) {
|
||||||
await deleteIcon()
|
await deleteIcon()
|
||||||
deletedIcon.value = false
|
deletedIcon.value = false
|
||||||
@@ -74,6 +77,7 @@ const onSaveChanges = useClientTry(async () => {
|
|||||||
icon.value = null
|
icon.value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always refresh after any change
|
||||||
await refreshOrganization()
|
await refreshOrganization()
|
||||||
|
|
||||||
addNotification({
|
addNotification({
|
||||||
|
|||||||
@@ -294,9 +294,10 @@ import FilesUploadDragAndDrop from '~/components/ui/servers/FilesUploadDragAndDr
|
|||||||
import FilesUploadDropdown from '~/components/ui/servers/FilesUploadDropdown.vue'
|
import FilesUploadDropdown from '~/components/ui/servers/FilesUploadDropdown.vue'
|
||||||
import FilesUploadZipUrlModal from '~/components/ui/servers/FilesUploadZipUrlModal.vue'
|
import FilesUploadZipUrlModal from '~/components/ui/servers/FilesUploadZipUrlModal.vue'
|
||||||
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'
|
import type { ModrinthServer } from '~/composables/servers/modrinth-servers.ts'
|
||||||
import { handleError } from '~/composables/servers/modrinth-servers.ts'
|
import { handleServersError } from '~/composables/servers/modrinth-servers.ts'
|
||||||
|
|
||||||
const { addNotification } = injectNotificationManager()
|
const notifications = injectNotificationManager()
|
||||||
|
const { addNotification } = notifications
|
||||||
const flags = useFeatureFlags()
|
const flags = useFeatureFlags()
|
||||||
const baseId = useId()
|
const baseId = useId()
|
||||||
|
|
||||||
@@ -584,7 +585,7 @@ const extractItem = async (path: string) => {
|
|||||||
await props.server.fs?.extractFile(path, true, false)
|
await props.server.fs?.extractFile(path, true, false)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error extracting item:', error)
|
console.error('Error extracting item:', error)
|
||||||
handleError(error)
|
handleServersError(error, notifications)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -598,11 +599,11 @@ const handleExtractItem = async (item: { name: string; type: string; path: strin
|
|||||||
uploadConflictModal.value.show(item.path, dry.conflicting_files)
|
uploadConflictModal.value.show(item.path, dry.conflicting_files)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
handleError(new Error('Error running dry run'))
|
handleServersError(new Error('Error running dry run'), notifications)
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error extracting item:', error)
|
console.error('Error extracting item:', error)
|
||||||
handleError(error)
|
handleServersError(error, notifications)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -267,7 +267,7 @@
|
|||||||
<button
|
<button
|
||||||
v-if="auth.user.auth_providers.includes(provider.id)"
|
v-if="auth.user.auth_providers.includes(provider.id)"
|
||||||
class="btn"
|
class="btn"
|
||||||
@click="removeAuthProvider(provider.id)"
|
@click="handleRemoveAuthProvider(provider.id)"
|
||||||
>
|
>
|
||||||
<TrashIcon /> Remove
|
<TrashIcon /> Remove
|
||||||
</button>
|
</button>
|
||||||
@@ -432,6 +432,7 @@ import SteamIcon from 'assets/icons/auth/sso-steam.svg'
|
|||||||
import QrcodeVue from 'qrcode.vue'
|
import QrcodeVue from 'qrcode.vue'
|
||||||
|
|
||||||
import Modal from '~/components/ui/Modal.vue'
|
import Modal from '~/components/ui/Modal.vue'
|
||||||
|
import { removeAuthProvider } from '~/composables/auth.js'
|
||||||
|
|
||||||
useHead({
|
useHead({
|
||||||
title: 'Account settings - Modrinth',
|
title: 'Account settings - Modrinth',
|
||||||
@@ -471,6 +472,14 @@ async function saveEmail() {
|
|||||||
stopLoading()
|
stopLoading()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleRemoveAuthProvider(provider) {
|
||||||
|
try {
|
||||||
|
await removeAuthProvider(provider)
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const managePasswordModal = ref()
|
const managePasswordModal = ref()
|
||||||
const removePasswordMode = ref(false)
|
const removePasswordMode = ref(false)
|
||||||
const oldPassword = ref('')
|
const oldPassword = ref('')
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ export class OrganizationContext {
|
|||||||
const EDIT_DETAILS = 1 << 2
|
const EDIT_DETAILS = 1 << 2
|
||||||
return (
|
return (
|
||||||
this.currentMember.value &&
|
this.currentMember.value &&
|
||||||
(this.currentMember.value.permissions & EDIT_DETAILS) === EDIT_DETAILS
|
(this.currentMember.value.permissions! & EDIT_DETAILS) === EDIT_DETAILS
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -89,7 +89,9 @@ export class OrganizationContext {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
public patchOrganization = async (newData: { slug: any }) => {
|
public patchOrganization = async (
|
||||||
|
newData: Partial<{ slug: string; name: string; description: string }>,
|
||||||
|
) => {
|
||||||
if (this.organization.value === null) {
|
if (this.organization.value === null) {
|
||||||
throw new Error('Organization is not set.')
|
throw new Error('Organization is not set.')
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user