feat(common): add foundational support for dropdown-based organization switcher (#5890)
This commit is contained in:
parent
a1be60da64
commit
faf2bfc8eb
5 changed files with 52 additions and 44 deletions
|
|
@ -2219,13 +2219,12 @@
|
|||
"admin": "Admin"
|
||||
},
|
||||
"organization_sidebar": {
|
||||
"instances": "Instances",
|
||||
"hoppscotch_cloud": "Hoppscotch Cloud",
|
||||
"admin": "Admin",
|
||||
"no_orgs_title": "No organizations yet",
|
||||
"no_orgs_description": "Join or create an organization to collaborate with your team",
|
||||
"error_loading": "Failed to load organizations",
|
||||
"inactive_orgs": "Inactive Organizations",
|
||||
"no_orgs_found": "No organizations found",
|
||||
"organizations_for": "Organizations for {email}",
|
||||
"multi_account_notice": "Each organization keeps its own login, using the last account accessed.",
|
||||
"inactive_orgs_tooltip": "Contact support for assistance."
|
||||
},
|
||||
|
|
|
|||
|
|
@ -45,6 +45,40 @@
|
|||
</template>
|
||||
</tippy>
|
||||
|
||||
<!-- Organization Switcher (Web/Cloud) -->
|
||||
<tippy
|
||||
v-else-if="
|
||||
platform.organization?.customOrganizationSwitcherComponent
|
||||
"
|
||||
interactive
|
||||
trigger="click"
|
||||
theme="popover"
|
||||
:on-shown="() => orgSwitcherRef?.focus()"
|
||||
:on-create="onOrgSwitcherCreate"
|
||||
>
|
||||
<HoppButtonSecondary
|
||||
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
:label="t('app.name')"
|
||||
:icon="IconChevronDown"
|
||||
reverse
|
||||
/>
|
||||
<template #content="{ hide }">
|
||||
<div
|
||||
ref="orgSwitcherRef"
|
||||
class="flex flex-col focus:outline-none min-w-72"
|
||||
tabindex="0"
|
||||
@keyup.escape="hide()"
|
||||
>
|
||||
<component
|
||||
:is="
|
||||
platform.organization.customOrganizationSwitcherComponent
|
||||
"
|
||||
@close-dropdown="hide()"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
</tippy>
|
||||
|
||||
<HoppButtonSecondary
|
||||
v-else
|
||||
class="!font-bold uppercase tracking-wide !text-secondaryDark hover:bg-primaryDark focus-visible:bg-primaryDark"
|
||||
|
|
@ -360,7 +394,9 @@ import { breakpointsTailwind, useBreakpoints, useNetwork } from "@vueuse/core"
|
|||
import { useService } from "dioc/vue"
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
import { pipe } from "fp-ts/function"
|
||||
import type { Instance } from "tippy.js"
|
||||
import { computed, onMounted, reactive, ref, watch } from "vue"
|
||||
|
||||
import { useToast } from "~/composables/toast"
|
||||
import { GetMyTeamsQuery, TeamAccessRole } from "~/helpers/backend/graphql"
|
||||
import { deleteTeam as backendDeleteTeam } from "~/helpers/backend/mutations/Team"
|
||||
|
|
@ -390,6 +426,16 @@ const downloadableLinksRef =
|
|||
kernelMode === "web" ? ref<any | null>(null) : ref(null)
|
||||
const instanceSwitcherRef =
|
||||
kernelMode === "desktop" ? ref<any | null>(null) : ref(null)
|
||||
const orgSwitcherRef = ref<HTMLElement | null>(null)
|
||||
|
||||
// Reserve scrollbar gutter so content width doesn't shift when the list
|
||||
// grows long enough to scroll inside the popover's `max-h-[45vh]` container.
|
||||
const onOrgSwitcherCreate = (instance: Instance) => {
|
||||
const content = instance.popper?.querySelector(".tippy-content")
|
||||
if (content instanceof HTMLElement) {
|
||||
content.style.scrollbarGutter = "stable"
|
||||
}
|
||||
}
|
||||
|
||||
const isUserAdmin = ref(false)
|
||||
|
||||
|
|
|
|||
|
|
@ -65,14 +65,6 @@
|
|||
<icon-lucide-help-circle class="svg-icons mb-4" />
|
||||
{{ t("error.something_went_wrong") }}
|
||||
</div>
|
||||
|
||||
<div v-if="showCreateOrganizationCTA" class="flex flex-col">
|
||||
<hr />
|
||||
<HoppButtonPrimary
|
||||
:label="t('organization.create_an_organization')"
|
||||
to="/orgs"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<TeamsAdd
|
||||
:show="showModalAdd"
|
||||
|
|
@ -174,12 +166,6 @@ const isActiveWorkspace = computed(() => (id: string) => {
|
|||
return workspace.value.teamID === id
|
||||
})
|
||||
|
||||
const showCreateOrganizationCTA = computed(() => {
|
||||
const { organization } = platform
|
||||
|
||||
return organization?.isDefaultCloudInstance ?? false
|
||||
})
|
||||
|
||||
const switchToTeamWorkspace = (team: GetMyTeamsQuery["myTeams"][number]) => {
|
||||
REMEMBERED_TEAM_ID.value = team.id
|
||||
workspaceService.changeWorkspace({
|
||||
|
|
|
|||
|
|
@ -16,16 +16,6 @@
|
|||
>
|
||||
<AppSidenav />
|
||||
</Pane>
|
||||
<Pane
|
||||
v-if="showOrgSidebar"
|
||||
style="width: auto; height: auto"
|
||||
class="hidden !overflow-auto md:flex md:flex-col"
|
||||
>
|
||||
<component
|
||||
:is="platform.organization.customOrganizationSidebarComponent"
|
||||
/>
|
||||
</Pane>
|
||||
<!-- Changed to !overflow-auto to allow organization sidebar and main content to scroll independently -->
|
||||
<Pane class="flex flex-1 !overflow-auto">
|
||||
<Splitpanes
|
||||
class="no-splitter"
|
||||
|
|
@ -121,14 +111,6 @@ const rootExtensionComponents = uiExtensionService.rootUIExtensionComponents
|
|||
|
||||
const HAS_OPENED_SPOTLIGHT = useSetting("HAS_OPENED_SPOTLIGHT")
|
||||
|
||||
// Show organization sidebar if organization switching is enabled and sidebar component is provided
|
||||
const showOrgSidebar = computed(() => {
|
||||
return (
|
||||
platform.organization?.organizationSwitchingEnabled === true &&
|
||||
platform.organization.customOrganizationSidebarComponent
|
||||
)
|
||||
})
|
||||
|
||||
onBeforeMount(() => {
|
||||
if (!mdAndLarger.value) {
|
||||
rightSidebar.value = false
|
||||
|
|
|
|||
|
|
@ -13,16 +13,11 @@ export type OrganizationPlatformDef = {
|
|||
initiateOnboarding: () => void
|
||||
|
||||
/**
|
||||
* Whether organization switching is enabled for this platform
|
||||
* If true, an organization switcher will be shown
|
||||
* Custom component for the organization switcher dropdown
|
||||
* If provided, will be shown as a dropdown in the header (like the instance switcher)
|
||||
* The component should emit 'close-dropdown' when the dropdown should close
|
||||
*/
|
||||
organizationSwitchingEnabled?: boolean
|
||||
|
||||
/**
|
||||
* Custom component for the organization sidebar
|
||||
* If provided, will be shown as a sidebar in the layout
|
||||
*/
|
||||
customOrganizationSidebarComponent?: Component
|
||||
customOrganizationSwitcherComponent?: Component
|
||||
|
||||
/**
|
||||
* Switch to a specific organization instance or default cloud instance
|
||||
|
|
|
|||
Loading…
Reference in a new issue