You've already forked AstralRinth
forked from didirus/AstralRinth
Merge commit '75e3994c6e57c2d3353084188b21f706d844ffb3' into beta
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
]
|
||||
},
|
||||
"productName": "AstralRinth App",
|
||||
"version": "0.10.1101",
|
||||
"version": "0.10.1201",
|
||||
"mainBinaryName": "AstralRinth App",
|
||||
"identifier": "AstralRinthApp",
|
||||
"plugins": {
|
||||
@@ -99,7 +99,7 @@
|
||||
],
|
||||
"csp": {
|
||||
"default-src": "'self' customprotocol: asset:",
|
||||
"connect-src": "ipc: https://git.astralium.su https://authserver.ely.by http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.posthog.com https://*.sentry.io https://api.mclo.gs 'self' data: blob:",
|
||||
"connect-src": "ipc: https://git.astralium.su https://authserver.ely.by http://ipc.localhost https://modrinth.com https://*.modrinth.com https://*.sentry.io https://api.mclo.gs 'self' data: blob:",
|
||||
"font-src": [
|
||||
"https://cdn-raw.modrinth.com/fonts/"
|
||||
],
|
||||
|
||||
@@ -1106,6 +1106,9 @@
|
||||
"profile.button.billing": {
|
||||
"message": "Manage user billing"
|
||||
},
|
||||
"profile.button.edit-role": {
|
||||
"message": "Edit role"
|
||||
},
|
||||
"profile.button.info": {
|
||||
"message": "View user details"
|
||||
},
|
||||
|
||||
@@ -2,6 +2,37 @@
|
||||
<div v-if="user" class="experimental-styles-within">
|
||||
<ModalCreation ref="modal_creation" />
|
||||
<CollectionCreateModal ref="modal_collection_creation" />
|
||||
<NewModal ref="editRoleModal" header="Edit role">
|
||||
<div class="flex w-80 flex-col gap-4">
|
||||
<div class="flex flex-col gap-2">
|
||||
<TeleportDropdownMenu
|
||||
v-model="selectedRole"
|
||||
:options="roleOptions"
|
||||
name="edit-role"
|
||||
placeholder="Select a role"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex justify-end gap-2">
|
||||
<ButtonStyled>
|
||||
<button @click="cancelRoleEdit">
|
||||
<XIcon />
|
||||
Cancel
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled color="brand">
|
||||
<button
|
||||
:disabled="!selectedRole || selectedRole === user.role || isSavingRole"
|
||||
@click="saveRoleEdit"
|
||||
>
|
||||
<template v-if="isSavingRole">
|
||||
<SpinnerIcon class="animate-spin" /> Saving...
|
||||
</template>
|
||||
<template v-else> <SaveIcon /> Save changes </template>
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
</NewModal>
|
||||
<NewModal v-if="auth.user && isStaff(auth.user)" ref="userDetailsModal" header="User details">
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex flex-col gap-1">
|
||||
@@ -127,6 +158,10 @@
|
||||
},
|
||||
{ id: 'copy-id', action: () => copyId() },
|
||||
{ id: 'copy-permalink', action: () => copyPermalink() },
|
||||
{
|
||||
divider: true,
|
||||
shown: auth.user && isAdmin(auth.user),
|
||||
},
|
||||
{
|
||||
id: 'open-billing',
|
||||
action: () => navigateTo(`/admin/billing/${user.id}`),
|
||||
@@ -137,6 +172,11 @@
|
||||
action: () => $refs.userDetailsModal.show(),
|
||||
shown: auth.user && isStaff(auth.user),
|
||||
},
|
||||
{
|
||||
id: 'edit-role',
|
||||
action: () => openRoleEditModal(),
|
||||
shown: auth.user && isAdmin(auth.user),
|
||||
},
|
||||
]"
|
||||
aria-label="More options"
|
||||
>
|
||||
@@ -165,6 +205,10 @@
|
||||
<InfoIcon aria-hidden="true" />
|
||||
{{ formatMessage(messages.infoButton) }}
|
||||
</template>
|
||||
<template #edit-role>
|
||||
<EditIcon aria-hidden="true" />
|
||||
{{ formatMessage(messages.editRoleButton) }}
|
||||
</template>
|
||||
</OverflowMenu>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
@@ -355,6 +399,8 @@ import {
|
||||
LockIcon,
|
||||
MoreVerticalIcon,
|
||||
ReportIcon,
|
||||
SaveIcon,
|
||||
SpinnerIcon,
|
||||
XIcon,
|
||||
} from '@modrinth/assets'
|
||||
import {
|
||||
@@ -362,10 +408,13 @@ import {
|
||||
ButtonStyled,
|
||||
commonMessages,
|
||||
ContentPageHeader,
|
||||
injectNotificationManager,
|
||||
NewModal,
|
||||
OverflowMenu,
|
||||
TeleportDropdownMenu,
|
||||
useRelativeTime,
|
||||
} from '@modrinth/ui'
|
||||
import { isAdmin } from '@modrinth/utils'
|
||||
import { IntlFormatted } from '@vintl/vintl/components'
|
||||
|
||||
import TenMClubBadge from '~/assets/images/badges/10m-club.svg?component'
|
||||
@@ -397,6 +446,8 @@ const formatCompactNumber = useCompactNumber(true)
|
||||
|
||||
const formatRelativeTime = useRelativeTime()
|
||||
|
||||
const { addNotification } = injectNotificationManager()
|
||||
|
||||
const messages = defineMessages({
|
||||
profileProjectsStats: {
|
||||
id: 'profile.stats.projects',
|
||||
@@ -471,6 +522,10 @@ const messages = defineMessages({
|
||||
id: 'profile.button.info',
|
||||
defaultMessage: 'View user details',
|
||||
},
|
||||
editRoleButton: {
|
||||
id: 'profile.button.edit-role',
|
||||
defaultMessage: 'Edit role',
|
||||
},
|
||||
userNotFoundError: {
|
||||
id: 'profile.error.not-found',
|
||||
defaultMessage: 'User not found',
|
||||
@@ -647,6 +702,55 @@ const navLinks = computed(() => [
|
||||
.slice()
|
||||
.sort((a, b) => a.label.localeCompare(b.label)),
|
||||
])
|
||||
|
||||
const selectedRole = ref(user.value.role)
|
||||
const isSavingRole = ref(false)
|
||||
|
||||
const roleOptions = ['developer', 'moderator', 'admin']
|
||||
|
||||
const editRoleModal = useTemplateRef('editRoleModal')
|
||||
|
||||
const openRoleEditModal = () => {
|
||||
selectedRole.value = user.value.role
|
||||
editRoleModal.value?.show()
|
||||
}
|
||||
|
||||
const cancelRoleEdit = () => {
|
||||
selectedRole.value = user.value.role
|
||||
editRoleModal.value?.hide()
|
||||
}
|
||||
|
||||
function saveRoleEdit() {
|
||||
if (!selectedRole.value || selectedRole.value === user.value.role) {
|
||||
return
|
||||
}
|
||||
|
||||
isSavingRole.value = true
|
||||
|
||||
useBaseFetch(`user/${user.value.id}`, {
|
||||
method: 'PATCH',
|
||||
body: {
|
||||
role: selectedRole.value,
|
||||
},
|
||||
})
|
||||
.then(() => {
|
||||
user.value.role = selectedRole.value
|
||||
|
||||
editRoleModal.value?.hide()
|
||||
})
|
||||
.catch(() => {
|
||||
console.error('Failed to update user role:', error)
|
||||
|
||||
addNotification({
|
||||
type: 'error',
|
||||
title: 'Failed to update role',
|
||||
message: 'An error occurred while updating the user role. Please try again.',
|
||||
})
|
||||
})
|
||||
.finally(() => {
|
||||
isSavingRole.value = false
|
||||
})
|
||||
}
|
||||
</script>
|
||||
<script>
|
||||
export default defineNuxtComponent({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT TRUE FROM mods WHERE organization_id = $1 AND status IN ('public', 'archived') LIMIT 1",
|
||||
"query": "SELECT TRUE FROM mods WHERE organization_id = $1 AND status IN ('approved', 'archived') LIMIT 1",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -18,5 +18,5 @@
|
||||
null
|
||||
]
|
||||
},
|
||||
"hash": "eb792d5033d7079fe3555593d8731f8853235275e4d5614636b5db524a4920d5"
|
||||
"hash": "829a4523233e957f8876d248a17ec04c245af41f43fa40aff9ee07e893dabf3a"
|
||||
}
|
||||
@@ -377,7 +377,7 @@ pub async fn is_visible_organization(
|
||||
// This is meant to match the same projects as the `Project::is_searchable` method, but we're not using
|
||||
// it here because that'd entail pulling in all projects for the organization
|
||||
let has_searchable_projects = sqlx::query_scalar!(
|
||||
"SELECT TRUE FROM mods WHERE organization_id = $1 AND status IN ('public', 'archived') LIMIT 1",
|
||||
"SELECT TRUE FROM mods WHERE organization_id = $1 AND status IN ('approved', 'archived') LIMIT 1",
|
||||
organization.id as database::models::ids::DBOrganizationId
|
||||
)
|
||||
.fetch_optional(pool)
|
||||
|
||||
@@ -80,11 +80,12 @@ impl CacheValueType {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the expiry time for entries of this type of cache item, in seconds.
|
||||
pub fn expiry(&self) -> i64 {
|
||||
match self {
|
||||
CacheValueType::File => 60 * 60 * 24 * 30, // 30 days
|
||||
CacheValueType::FileHash => 60 * 60 * 24 * 30, // 30 days
|
||||
_ => 60 * 60 * 30, // 30 minutes
|
||||
CacheValueType::File => 30 * 24 * 60 * 60, // 30 days
|
||||
CacheValueType::FileHash => 30 * 24 * 60 * 60, // 30 days
|
||||
_ => 30 * 60, // 30 minutes
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,20 @@ export type VersionEntry = {
|
||||
}
|
||||
|
||||
const VERSIONS: VersionEntry[] = [
|
||||
{
|
||||
date: `2025-10-15T12:15:00-07:00`,
|
||||
product: 'app',
|
||||
version: '0.10.12',
|
||||
body: `## Improvements
|
||||
- Fixed cache sticking around for way too long (30 hours instead of 30 minutes).`,
|
||||
},
|
||||
{
|
||||
date: `2025-10-15T04:11:00-07:00`,
|
||||
product: 'app',
|
||||
version: '0.10.11',
|
||||
body: `## Improvements
|
||||
- Fixed ads being able to play audio.`,
|
||||
},
|
||||
{
|
||||
date: `2025-10-14T18:45:00-07:00`,
|
||||
product: 'servers',
|
||||
|
||||
Reference in New Issue
Block a user