You've already forked AstralRinth
forked from didirus/AstralRinth
Creator update hotfixes
* Responsive avatar sizing fix * random mounting bug * User owned project list correctly filtered * fix accepted member count * Leave team fix * Remove debug * Remove debug * hide view button if collections view
This commit is contained in:
@@ -91,7 +91,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<template
|
<template
|
||||||
v-if="
|
v-if="
|
||||||
project.versions.length !== 0 &&
|
project.versions?.length !== 0 &&
|
||||||
project.project_type !== 'resourcepack' &&
|
project.project_type !== 'resourcepack' &&
|
||||||
project.project_type !== 'plugin' &&
|
project.project_type !== 'plugin' &&
|
||||||
project.project_type !== 'shader' &&
|
project.project_type !== 'shader' &&
|
||||||
|
|||||||
@@ -274,8 +274,8 @@
|
|||||||
<div class="stats">
|
<div class="stats">
|
||||||
<UsersIcon />
|
<UsersIcon />
|
||||||
<span>
|
<span>
|
||||||
{{ props.organization.members?.length || 0 }} member<template
|
{{ acceptedOrgMembers.length }} member<template
|
||||||
v-if="props.organization.members?.length !== 1"
|
v-if="acceptedOrgMembers.length !== 1"
|
||||||
>s</template
|
>s</template
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
@@ -580,6 +580,10 @@ const auth = await useAuth()
|
|||||||
const allTeamMembers = ref([])
|
const allTeamMembers = ref([])
|
||||||
const allOrgMembers = ref([])
|
const allOrgMembers = ref([])
|
||||||
|
|
||||||
|
const acceptedOrgMembers = computed(() => {
|
||||||
|
return props.organization?.members?.filter((x) => x.accepted) || []
|
||||||
|
})
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
[
|
[
|
||||||
() => props.allMembers,
|
() => props.allMembers,
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
:key="org.id"
|
:key="org.id"
|
||||||
:to="`/organization/${org.slug}`"
|
:to="`/organization/${org.slug}`"
|
||||||
class="universal-card button-base recessed org"
|
class="universal-card button-base recessed org"
|
||||||
:class="{ 'is-disabled': org.members?.length === 0 }"
|
:class="{ 'is-disabled': onlyAcceptedMembers(org.members).length === 0 }"
|
||||||
>
|
>
|
||||||
<Avatar :src="org.icon_url" :alt="org.name" class="icon" />
|
<Avatar :src="org.icon_url" :alt="org.name" class="icon" />
|
||||||
<div class="details">
|
<div class="details">
|
||||||
@@ -32,7 +32,8 @@
|
|||||||
<div class="stats">
|
<div class="stats">
|
||||||
<UsersIcon />
|
<UsersIcon />
|
||||||
<span>
|
<span>
|
||||||
{{ org.members?.length || 0 }} member<template v-if="org.members?.length !== 1"
|
{{ onlyAcceptedMembers(org.members).length }} member<template
|
||||||
|
v-if="onlyAcceptedMembers(org.members).length !== 1"
|
||||||
>s</template
|
>s</template
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
@@ -66,6 +67,8 @@ const { data: orgs, error } = useAsyncData('organizations', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const onlyAcceptedMembers = (members) => members.filter((member) => member?.accepted)
|
||||||
|
|
||||||
if (error.value) {
|
if (error.value) {
|
||||||
createError({
|
createError({
|
||||||
statusCode: 500,
|
statusCode: 500,
|
||||||
@@ -102,13 +105,13 @@ const openCreateOrgModal = () => {
|
|||||||
|
|
||||||
.org {
|
.org {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: auto 1fr;
|
grid-template-columns: max-content 1fr;
|
||||||
gap: var(--gap-md);
|
gap: var(--gap-md);
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
width: 100% !important;
|
width: 100% !important;
|
||||||
height: 6rem !important;
|
height: min(6rem, 20vw) !important;
|
||||||
max-width: unset !important;
|
max-width: unset !important;
|
||||||
max-height: unset !important;
|
max-height: unset !important;
|
||||||
aspect-ratio: 1 / 1;
|
aspect-ratio: 1 / 1;
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
organizationPermissions.MANAGE_INVITES
|
organizationPermissions.MANAGE_INVITES
|
||||||
)
|
)
|
||||||
"
|
"
|
||||||
@keypress.enter="() => onInviteTeamMember(organization.team_id, currentUsername)"
|
@keypress.enter="() => onInviteTeamMember(organization.team, currentUsername)"
|
||||||
/>
|
/>
|
||||||
<label for="username" class="hidden">Username</label>
|
<label for="username" class="hidden">Username</label>
|
||||||
<Button
|
<Button
|
||||||
@@ -49,7 +49,11 @@
|
|||||||
Remove yourself as a member of this organization.
|
Remove yourself as a member of this organization.
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<Button color="danger" :disabled="currentMember.role === 'Owner'" @click="leaveProject()">
|
<Button
|
||||||
|
color="danger"
|
||||||
|
:disabled="currentMember.role === 'Owner'"
|
||||||
|
@click="() => onLeaveProject(organization.team_id, auth.user.id)"
|
||||||
|
>
|
||||||
<UserRemoveIcon />
|
<UserRemoveIcon />
|
||||||
Leave organization
|
Leave organization
|
||||||
</Button>
|
</Button>
|
||||||
@@ -287,11 +291,13 @@ const permToLabel = (key) => {
|
|||||||
return o.charAt(0).toUpperCase() + o.slice(1).toLowerCase()
|
return o.charAt(0).toUpperCase() + o.slice(1).toLowerCase()
|
||||||
}
|
}
|
||||||
|
|
||||||
const leaveProject = async () => {
|
const leaveProject = async (teamId, uid) => {
|
||||||
await removeTeamMember(organization.value.team_id, auth.user.id)
|
await removeTeamMember(teamId, uid)
|
||||||
await navigateTo(`/organization/${organization.value.slug}`)
|
await navigateTo(`/organization/${organization.value.id}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onLeaveProject = useClientTry(leaveProject)
|
||||||
|
|
||||||
const onInviteTeamMember = useClientTry(async (teamId, username) => {
|
const onInviteTeamMember = useClientTry(async (teamId, username) => {
|
||||||
const user = await useBaseFetch(`user/${username}`)
|
const user = await useBaseFetch(`user/${username}`)
|
||||||
const data = {
|
const data = {
|
||||||
|
|||||||
@@ -166,7 +166,7 @@
|
|||||||
Create a project
|
Create a project
|
||||||
</Button>
|
</Button>
|
||||||
<OrganizationProjectTransferModal
|
<OrganizationProjectTransferModal
|
||||||
:projects="userProjects || []"
|
:projects="usersOwnedProjects || []"
|
||||||
@submit="onProjectTransferSubmit"
|
@submit="onProjectTransferSubmit"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -325,7 +325,7 @@ const { organization, projects, refresh } = inject('organizationContext')
|
|||||||
|
|
||||||
const auth = await useAuth()
|
const auth = await useAuth()
|
||||||
|
|
||||||
const { data: userProjects } = await useAsyncData(
|
const { data: userProjects, refresh: refreshUserProjects } = await useAsyncData(
|
||||||
`user/${auth.value.user.id}/projects`,
|
`user/${auth.value.user.id}/projects`,
|
||||||
() => useBaseFetch(`user/${auth.value.user.id}/projects`),
|
() => useBaseFetch(`user/${auth.value.user.id}/projects`),
|
||||||
{
|
{
|
||||||
@@ -333,6 +333,34 @@ const { data: userProjects } = await useAsyncData(
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const usersOwnedProjects = ref([])
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => userProjects.value,
|
||||||
|
async () => {
|
||||||
|
if (!userProjects.value) return
|
||||||
|
if (!userProjects.value.length) return
|
||||||
|
|
||||||
|
const projects = userProjects.value.filter((project) => project.organization === null)
|
||||||
|
|
||||||
|
const teamIds = projects.map((project) => project?.team).filter((x) => x)
|
||||||
|
// Shape of teams is member[][]
|
||||||
|
const teams = await useBaseFetch(`teams?ids=${JSON.stringify(teamIds)}`, {
|
||||||
|
apiVersion: 3,
|
||||||
|
})
|
||||||
|
// for each team id, figure out if the user is a member, and is_owner. Then filter the projects to only include those that are owned by the user
|
||||||
|
const ownedTeamIds = teamIds.filter((_tid, i) => {
|
||||||
|
const team = teams?.[i]
|
||||||
|
if (!team) return false
|
||||||
|
const member = team.find((member) => member.user.id === auth.value.user.id)
|
||||||
|
return member && member.is_owner
|
||||||
|
})
|
||||||
|
const ownedProjects = projects.filter((project) => ownedTeamIds.includes(project.team))
|
||||||
|
usersOwnedProjects.value = ownedProjects
|
||||||
|
}, // watch options
|
||||||
|
{ immediate: true, deep: true }
|
||||||
|
)
|
||||||
|
|
||||||
const onProjectTransferSubmit = async (projects) => {
|
const onProjectTransferSubmit = async (projects) => {
|
||||||
try {
|
try {
|
||||||
for (const project of projects) {
|
for (const project of projects) {
|
||||||
@@ -346,6 +374,7 @@ const onProjectTransferSubmit = async (projects) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await refresh()
|
await refresh()
|
||||||
|
await refreshUserProjects()
|
||||||
|
|
||||||
addNotification({
|
addNotification({
|
||||||
group: 'main',
|
group: 'main',
|
||||||
|
|||||||
@@ -201,6 +201,7 @@
|
|||||||
{{ formatMessage(messages.profileManageProjectsButton) }}
|
{{ formatMessage(messages.profileManageProjectsButton) }}
|
||||||
</NuxtLink>
|
</NuxtLink>
|
||||||
<button
|
<button
|
||||||
|
v-if="route.params.projectType !== 'collections'"
|
||||||
v-tooltip="
|
v-tooltip="
|
||||||
formatMessage(commonMessages[`${cosmetics.searchDisplayMode.user}InputView`])
|
formatMessage(commonMessages[`${cosmetics.searchDisplayMode.user}InputView`])
|
||||||
"
|
"
|
||||||
|
|||||||
Reference in New Issue
Block a user