192 lines
6.6 KiB
Vue
192 lines
6.6 KiB
Vue
<template>
|
|
<div class="inline-block">
|
|
<Menu as="div" class="flex items-center">
|
|
<MenuButton :id="menuButtonId" v-slot="{ open: userOpen }" class="w-full">
|
|
<span class="sr-only">Open workspace menu</span>
|
|
<div class="flex items-center gap-2 p-0.5 pr-1.5 hover:bg-highlight-2 rounded">
|
|
<div class="relative">
|
|
<WorkspaceAvatar
|
|
:name="activeWorkspace?.name || 'Personal projects'"
|
|
:logo="activeWorkspace?.logo"
|
|
/>
|
|
<div
|
|
v-if="hasDiscoverableWorkspaces"
|
|
class="absolute -top-[4px] -right-[4px] size-3 border-[2px] border-foundation-page bg-danger rounded-full"
|
|
/>
|
|
</div>
|
|
<p class="text-body-xs text-foreground truncate max-w-40">
|
|
{{ activeWorkspace?.name || 'Personal projects' }}
|
|
</p>
|
|
<ChevronDownIcon
|
|
:class="userOpen ? 'rotate-180' : ''"
|
|
class="h-3 w-3 flex-shrink-0"
|
|
/>
|
|
</div>
|
|
</MenuButton>
|
|
<Transition
|
|
enter-active-class="transition ease-out duration-200"
|
|
enter-from-class="transform opacity-0 scale-95"
|
|
enter-to-class="transform opacity-100 scale-100"
|
|
leave-active-class="transition ease-in duration-75"
|
|
leave-from-class="transform opacity-100 scale-100"
|
|
leave-to-class="transform opacity-0 scale-95"
|
|
>
|
|
<MenuItems
|
|
class="absolute left-2 lg:left-3 top-[3.2rem] lg:top-14 w-[17rem] origin-top-right bg-foundation outline outline-1 outline-primary-muted rounded-md shadow-lg overflow-hidden"
|
|
>
|
|
<HeaderWorkspaceSwitcherHeaderProjects v-if="!activeWorkspace" />
|
|
<HeaderWorkspaceSwitcherHeaderSsoExpired
|
|
v-else-if="ssoExpiredWorkspace"
|
|
:workspace="ssoExpiredWorkspace"
|
|
/>
|
|
<HeaderWorkspaceSwitcherHeaderWorkspace
|
|
v-else-if="activeWorkspace.role"
|
|
:workspace="fullActiveWorkspace"
|
|
@open-invite-dialog="isInviteDialogOpen = true"
|
|
/>
|
|
<HeaderWorkspaceSwitcherHeader
|
|
v-else
|
|
:name="activeWorkspace?.name"
|
|
:logo="activeWorkspace?.logo"
|
|
:to="workspaceRoute(activeWorkspace?.slug)"
|
|
>
|
|
<p class="text-body-xs text-foreground-2">
|
|
You are not part of this workspace.
|
|
</p>
|
|
</HeaderWorkspaceSwitcherHeader>
|
|
<HeaderWorkspaceSwitcherList class="border-t border-outline-2" />
|
|
<MenuItem v-if="hasDiscoverableWorkspacesOrJoinRequests">
|
|
<div class="p-2 border-t border-outline-2">
|
|
<NuxtLink
|
|
class="flex justify-between items-center cursor-pointer hover:bg-highlight-1 py-1 px-2 rounded"
|
|
@click="showDiscoverableWorkspacesModal = true"
|
|
>
|
|
<p class="text-body-xs text-foreground">Join existing workspaces</p>
|
|
<div class="relative">
|
|
<CommonBadge v-if="hasDiscoverableWorkspacesOrJoinRequests" rounded>
|
|
{{ discoverableWorkspacesAndJoinRequestsCount }}
|
|
</CommonBadge>
|
|
<div
|
|
v-if="hasDiscoverableWorkspaces"
|
|
class="absolute -top-[4px] -right-[4px] size-3 border-[2px] border-foundation-page bg-danger rounded-full"
|
|
/>
|
|
</div>
|
|
</NuxtLink>
|
|
</div>
|
|
</MenuItem>
|
|
</MenuItems>
|
|
</Transition>
|
|
</Menu>
|
|
|
|
<InviteDialogWorkspace
|
|
v-model:open="isInviteDialogOpen"
|
|
:workspace="fullActiveWorkspace"
|
|
/>
|
|
|
|
<WorkspaceDiscoverableWorkspacesModal
|
|
v-model:open="showDiscoverableWorkspacesModal"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { Menu, MenuButton, MenuItems, MenuItem } from '@headlessui/vue'
|
|
import { useQuery } from '@vue/apollo-composable'
|
|
import {
|
|
navigationWorkspaceSwitcherQuery,
|
|
workspaceSwitcherHeaderWorkspaceQuery
|
|
} from '~/lib/navigation/graphql/queries'
|
|
import { ChevronDownIcon } from '@heroicons/vue/24/outline'
|
|
import { WorkspaceJoinRequestStatus } from '~/lib/common/generated/gql/graphql'
|
|
import { graphql } from '~/lib/common/generated/gql'
|
|
import { workspaceRoute } from '~/lib/common/helpers/route'
|
|
|
|
graphql(`
|
|
fragment WorkspaceSwitcherActiveWorkspace_LimitedWorkspace on LimitedWorkspace {
|
|
id
|
|
name
|
|
logo
|
|
slug
|
|
role
|
|
}
|
|
`)
|
|
|
|
graphql(`
|
|
fragment WorkspaceSwitcherActiveWorkspace_User on User {
|
|
id
|
|
activeWorkspace {
|
|
...WorkspaceSwitcherActiveWorkspace_LimitedWorkspace
|
|
}
|
|
expiredSsoSessions {
|
|
id
|
|
...HeaderWorkspaceSwitcherHeaderExpiredSso_LimitedWorkspace
|
|
}
|
|
discoverableWorkspaces {
|
|
id
|
|
}
|
|
workspaceJoinRequests(filter: $joinRequestFilter) {
|
|
totalCount
|
|
}
|
|
}
|
|
`)
|
|
|
|
const { $intercom } = useNuxtApp()
|
|
const isWorkspacesEnabled = useIsWorkspacesEnabled()
|
|
const menuButtonId = useId()
|
|
const { result, onResult: onActiveWorkspaceResult } = useQuery(
|
|
navigationWorkspaceSwitcherQuery,
|
|
() => ({
|
|
joinRequestFilter: {
|
|
status: WorkspaceJoinRequestStatus.Pending
|
|
}
|
|
}),
|
|
() => ({
|
|
enabled: isWorkspacesEnabled.value
|
|
})
|
|
)
|
|
// Seperate query to get the full workspace, because it's not always needed
|
|
const { result: fullWorkspaceResult } = useQuery(
|
|
workspaceSwitcherHeaderWorkspaceQuery,
|
|
() => ({
|
|
slug: result.value?.activeUser?.activeWorkspace?.slug || ''
|
|
}),
|
|
{
|
|
enabled:
|
|
!!result.value?.activeUser?.activeWorkspace?.slug &&
|
|
isWorkspacesEnabled.value &&
|
|
!!result.value?.activeUser?.activeWorkspace?.role
|
|
}
|
|
)
|
|
|
|
const showDiscoverableWorkspacesModal = ref(false)
|
|
const isInviteDialogOpen = ref(false)
|
|
|
|
const activeWorkspace = computed(() => result.value?.activeUser?.activeWorkspace)
|
|
const fullActiveWorkspace = computed(() => fullWorkspaceResult.value?.workspaceBySlug)
|
|
const ssoExpiredWorkspace = computed(() =>
|
|
result.value?.activeUser?.expiredSsoSessions?.find(
|
|
(session) => session.slug === activeWorkspace.value?.slug
|
|
)
|
|
)
|
|
const hasDiscoverableWorkspaces = computed(
|
|
() => (result.value?.activeUser?.discoverableWorkspaces?.length || 0) > 0
|
|
)
|
|
const discoverableWorkspacesAndJoinRequestsCount = computed(
|
|
() =>
|
|
(result.value?.activeUser?.discoverableWorkspaces?.length || 0) +
|
|
(result.value?.activeUser?.workspaceJoinRequests?.totalCount || 0)
|
|
)
|
|
const hasDiscoverableWorkspacesOrJoinRequests = computed(
|
|
() => discoverableWorkspacesAndJoinRequestsCount.value > 0
|
|
)
|
|
|
|
onActiveWorkspaceResult(({ data }) => {
|
|
if (data?.activeUser?.activeWorkspace) {
|
|
$intercom.updateCompany({
|
|
id: data.activeUser.activeWorkspace.id,
|
|
name: data.activeUser.activeWorkspace.name
|
|
})
|
|
}
|
|
})
|
|
</script>
|