Skip to content

Commit 6e39aa5

Browse files
committed
feat: add organization picker popover and update sidebar navigation (#16760)
1 parent 1cb800e commit 6e39aa5

File tree

11 files changed

+389
-157
lines changed

11 files changed

+389
-157
lines changed

airbyte-webapp/src/area/layout/SideBar/SideBar.tsx

Lines changed: 53 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { useAuthService } from "core/services/auth";
1515
import { FeatureItem, useFeature } from "core/services/features";
1616
import { useIsCloudApp } from "core/utils/app";
1717
import { Intent, useGeneratedIntent, useIntent } from "core/utils/rbac";
18+
import { useExperiment } from "hooks/services/Experiment";
1819
import { useGetConnectorsOutOfDate } from "hooks/services/useConnector";
1920
import { CloudHelpDropdown } from "packages/cloud/views/layout/CloudMainView/CloudHelpDropdown";
2021
import { CloudSettingsRoutePaths } from "packages/cloud/views/settings/routePaths";
@@ -36,7 +37,7 @@ const WorkspaceNavItems = () => {
3637
const workspaceId = useCurrentWorkspaceId();
3738
const basePath = `${RoutePaths.Workspaces}/${workspaceId}/`;
3839
return (
39-
<>
40+
<MenuContent data-testid="navMainItems">
4041
<NavItem
4142
label={<FormattedMessage id="sidebar.connections" />}
4243
icon="connection"
@@ -62,66 +63,76 @@ const WorkspaceNavItems = () => {
6263
to={basePath + RoutePaths.ConnectorBuilder}
6364
/>
6465
<NavItem
65-
label={<FormattedMessage id="sidebar.settings" />}
66+
label={<FormattedMessage id="sidebar.workspaceSettings" />}
6667
icon="gear"
6768
to={basePath + RoutePaths.Settings}
6869
withNotification={hasNewVersions}
6970
/>
70-
</>
71+
</MenuContent>
7172
);
7273
};
7374

7475
const OrganizationNavItems = () => {
7576
const organizationId = useCurrentOrganizationId();
7677
const multiWorkspaceUI = useFeature(FeatureItem.MultiWorkspaceUI);
7778
const displayOrganizationUsers = useFeature(FeatureItem.DisplayOrganizationUsers);
78-
const canViewOrgSettings = useIntent("ViewOrganizationSettings", { organizationId });
79+
const canViewOrganizationSettings = useIntent("ViewOrganizationSettings", { organizationId });
7980
const canManageOrganizationBilling = useGeneratedIntent(Intent.ManageOrganizationBilling, { organizationId });
8081
const canViewOrganizationUsage = useGeneratedIntent(Intent.ViewOrganizationUsage, { organizationId });
82+
const canManageEmbedded = useGeneratedIntent(Intent.ViewConfigTemplates, { organizationId });
83+
const allowConfigTemplateEndpoints = useExperiment("platform.allow-config-template-endpoints");
84+
const isCloudApp = useIsCloudApp();
8185
const basePath = `${RoutePaths.Organization}/${organizationId}/`;
8286
return (
83-
<>
84-
{multiWorkspaceUI && canViewOrgSettings && (
85-
<>
87+
<MenuContent data-testid="navMainItems">
88+
{multiWorkspaceUI && (
89+
<NavItem
90+
label={<FormattedMessage id="workspaces.title" />}
91+
icon="grid"
92+
to={basePath + RoutePaths.Workspaces}
93+
testId="workspacesLink"
94+
/>
95+
)}
96+
{isCloudApp && canManageEmbedded && allowConfigTemplateEndpoints && (
97+
<NavItem
98+
icon="stars"
99+
label={<FormattedMessage id="settings.embedded" />}
100+
to={`${basePath + RoutePaths.Settings}/${CloudSettingsRoutePaths.Embedded}`} // Make sure this is correct
101+
testId="embeddedLink"
102+
/>
103+
)}
104+
{(multiWorkspaceUI && canViewOrganizationSettings && displayOrganizationUsers) ||
105+
(isCloudApp && canViewOrganizationSettings && (
86106
<NavItem
87-
label={<FormattedMessage id="workspaces.title" />}
88-
icon="grid"
89-
to={basePath + RoutePaths.Workspaces}
90-
testId="workspacesLink"
107+
label={<FormattedMessage id="settings.members" />}
108+
icon="community"
109+
to={basePath + SettingsRoutePaths.OrganizationMembers}
110+
testId="organizationMembersLink"
91111
/>
92-
{displayOrganizationUsers && (
93-
<NavItem
94-
label={<FormattedMessage id="settings.members" />}
95-
icon="community"
96-
to={basePath + SettingsRoutePaths.OrganizationMembers}
97-
testId="organizationMembersLink"
98-
/>
99-
)}
100-
{canManageOrganizationBilling && (
101-
<NavItem
102-
label={<FormattedMessage id="sidebar.billing" />}
103-
icon="credits"
104-
to={basePath + CloudSettingsRoutePaths.Billing}
105-
testId="billingLink"
106-
/>
107-
)}
108-
{canViewOrganizationUsage && (
109-
<NavItem
110-
label={<FormattedMessage id="settings.usage" />}
111-
icon="chart"
112-
to={basePath + CloudSettingsRoutePaths.OrganizationUsage}
113-
testId="organizationUsageLink"
114-
/>
115-
)}
116-
</>
112+
))}
113+
{isCloudApp && canViewOrganizationSettings && canManageOrganizationBilling && (
114+
<NavItem
115+
label={<FormattedMessage id="sidebar.billing" />}
116+
icon="credits"
117+
to={basePath + CloudSettingsRoutePaths.Billing}
118+
testId="billingLink"
119+
/>
120+
)}
121+
{isCloudApp && canViewOrganizationSettings && canViewOrganizationUsage && (
122+
<NavItem
123+
label={<FormattedMessage id="settings.usage" />}
124+
icon="chart"
125+
to={basePath + CloudSettingsRoutePaths.OrganizationUsage}
126+
testId="organizationUsageLink"
127+
/>
117128
)}
118129
<NavItem
119130
label={<FormattedMessage id="settings.organizationSettings" />}
120131
icon="gear"
121132
to={basePath + RoutePaths.Settings}
122133
testId="orgSettingsLink"
123134
/>
124-
</>
135+
</MenuContent>
125136
);
126137
};
127138

@@ -132,8 +143,8 @@ export const SideBar: React.FC<PropsWithChildren> = () => {
132143
const isHidden = HIDDEN_SIDEBAR_PATHS.some((path) => !!matchPath(path, pathname));
133144
const isCloudApp = useIsCloudApp();
134145

135-
const organizationId = useCurrentOrganizationId();
136-
const showOrgNav = Boolean(organizationId);
146+
const showOrganizationNav = pathname.split("/")[1] === RoutePaths.Organization;
147+
const showWorkspaceNav = pathname.split("/")[1] === RoutePaths.Workspaces;
137148

138149
const username =
139150
authType === "simple" || authType === "none"
@@ -145,14 +156,13 @@ export const SideBar: React.FC<PropsWithChildren> = () => {
145156
return (
146157
<nav className={classNames(styles.sidebar, { [styles.hidden]: isHidden })}>
147158
<AirbyteOrgPicker />
148-
{/* NOTE: AdminWorkspaceWarning wants a workspace */}
159+
{/* NOTE: AdminWorkspaceWarning wants a workspace but one is not always available: https://github.com/airbytehq/airbyte-internal-issues/issues/12948 */}
149160
{/* <IfFeatureEnabled feature={FeatureItem.ShowAdminWarningInWorkspace}>
150161
<AdminWorkspaceWarning />
151162
</IfFeatureEnabled> */}
152163
<FlexContainer className={styles.sidebar__menuItems} direction="column" justifyContent="flex-start">
153-
<MenuContent data-testid="navMainItems">
154-
{showOrgNav ? <OrganizationNavItems /> : <WorkspaceNavItems />}
155-
</MenuContent>
164+
{showOrganizationNav && <OrganizationNavItems />}
165+
{showWorkspaceNav && <WorkspaceNavItems />}
156166
<Box className={styles.sidebar__menuContentSeparator} />
157167
<MenuContent>
158168
{isCloudApp ? <CloudHelpDropdown /> : <HelpDropdown />}
Lines changed: 24 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,96 +1,61 @@
11
@use "scss/colors";
22
@use "scss/variables";
3+
@use "scss/z-indices";
34

45
.orgPicker {
6+
position: relative;
57
width: 100%;
6-
display: flex;
7-
justify-content: space-between;
8-
align-items: center;
9-
gap: variables.$spacing-sm;
108
border-bottom: variables.$border-thin solid colors.$grey-100;
11-
height: 58px;
12-
13-
> *:first-child {
14-
width: 100%;
15-
height: 100%;
16-
}
9+
height: variables.$height-org-picker;
1710
}
1811

19-
.orgPicker__dropdownButton {
20-
display: flex;
21-
align-items: center;
12+
.orgPicker__button {
2213
width: 100%;
2314
height: 100%;
2415
background: none;
2516
border: none;
2617
padding: 0 variables.$spacing-sm;
2718
cursor: pointer;
19+
transition: all 0.3s ease-out;
2820
border-radius: variables.$border-radius-sm;
2921

3022
&:focus-visible {
31-
outline: variables.$border-thick solid colors.$blue-500;
32-
outline-offset: variables.$border-thick;
33-
border-radius: variables.$border-radius-sm;
23+
outline-offset: -2px;
3424
}
3525

3626
.orgPicker__logo {
3727
width: 24px;
38-
height: 37px;
28+
height: 24px;
3929
flex-shrink: 0;
4030
}
4131

42-
.orgPicker__workspace {
43-
flex: 1;
44-
min-width: 0;
45-
text-align: left;
32+
.orgPicker__textBlock {
4633
display: flex;
4734
flex-direction: column;
48-
margin: 0 variables.$spacing-md;
49-
50-
.orgPicker__workspaceName,
51-
.orgPicker__orgName {
52-
text-align: left;
53-
white-space: nowrap;
54-
overflow: hidden;
55-
text-overflow: ellipsis;
56-
line-height: 18px;
57-
font-weight: 500;
58-
font-size: variables.$font-size-sm;
59-
}
60-
}
61-
62-
.orgPicker__chevron {
63-
display: flex;
64-
align-items: center;
65-
width: 14px;
66-
height: 14px;
67-
color: colors.$grey-400;
68-
flex-shrink: 0;
35+
justify-content: center;
36+
min-width: 0;
37+
flex: 1;
38+
margin: 0 variables.$spacing-sm;
39+
cursor: pointer;
6940
}
70-
}
71-
72-
.orgPicker__dropdownMenuItem {
73-
width: 240px;
74-
min-height: 26px;
75-
display: flex;
76-
align-items: center;
77-
justify-content: space-between;
78-
flex-direction: row;
79-
padding: 0 variables.$spacing-md;
8041

81-
.dropdownMenu__orgName {
82-
flex: 1;
42+
.orgPicker__workspaceName,
43+
.orgPicker__orgName {
8344
text-align: left;
8445
white-space: nowrap;
8546
overflow: hidden;
8647
text-overflow: ellipsis;
87-
line-height: 20px;
48+
line-height: 18px;
8849
font-weight: 500;
8950
font-size: variables.$font-size-sm;
90-
padding-left: variables.$spacing-md;
51+
cursor: pointer;
9152
}
53+
}
9254

93-
.orgPicker__gearIcon {
94-
color: colors.$grey-400;
95-
}
55+
.orgPicker__popoverPanel {
56+
width: 240px;
57+
background: colors.$foreground;
58+
border-radius: variables.$border-radius-sm;
59+
box-shadow: variables.$box-shadow-raised;
60+
z-index: z-indices.$dropdownMenu;
9661
}

0 commit comments

Comments
 (0)