Skip to content

Commit d95e7d3

Browse files
committed
feat: add user settings routes and layout (#16748)
1 parent f75fd45 commit d95e7d3

File tree

7 files changed

+124
-6
lines changed

7 files changed

+124
-6
lines changed

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

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ const OrganizationNavItems = () => {
7676
const multiWorkspaceUI = useFeature(FeatureItem.MultiWorkspaceUI);
7777
const displayOrganizationUsers = useFeature(FeatureItem.DisplayOrganizationUsers);
7878
const canViewOrgSettings = useIntent("ViewOrganizationSettings", { organizationId });
79-
const canManageOrganizationBilling = useGeneratedIntent(Intent.ManageOrganizationBilling);
80-
const canViewOrganizationUsage = useGeneratedIntent(Intent.ViewOrganizationUsage);
79+
const canManageOrganizationBilling = useGeneratedIntent(Intent.ManageOrganizationBilling, { organizationId });
80+
const canViewOrganizationUsage = useGeneratedIntent(Intent.ViewOrganizationUsage, { organizationId });
8181
const basePath = `${RoutePaths.Organization}/${organizationId}/`;
8282
return (
8383
<>
@@ -140,6 +140,8 @@ export const SideBar: React.FC<PropsWithChildren> = () => {
140140
? formatMessage({ id: "sidebar.defaultUsername" })
141141
: user?.name?.trim() || user?.email?.trim();
142142

143+
const basePath = pathname.split("/").slice(0, 3).join("/");
144+
143145
return (
144146
<nav className={classNames(styles.sidebar, { [styles.hidden]: isHidden })}>
145147
<AirbyteOrgPicker />
@@ -164,7 +166,7 @@ export const SideBar: React.FC<PropsWithChildren> = () => {
164166
options={[
165167
{
166168
as: "a",
167-
href: RoutePaths.Settings, // NOTE: This needs to be fixed once user paths are set up
169+
href: `${basePath}/${SettingsRoutePaths.User}`,
168170
displayName: formatMessage({ id: "sidebar.userSettings" }),
169171
internal: true,
170172
icon: <Icon type="gear" />,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import React from "react";
2+
import { Navigate, Route, Routes } from "react-router-dom";
3+
4+
import { CloudSettingsRoutePaths } from "packages/cloud/views/settings/routePaths";
5+
import { SettingsRoutePaths } from "pages/routePaths";
6+
7+
import { UserSettingsLayout } from "./components/UserSettingsLayout";
8+
9+
const AccountSettingsView = React.lazy(() =>
10+
import("packages/cloud/views/users/AccountSettingsView/AccountSettingsView").then((module) => ({
11+
default: module.AccountSettingsView,
12+
}))
13+
);
14+
const ApplicationsView = React.lazy(() =>
15+
import("packages/cloud/views/users/ApplicationSettingsView/ApplicationSettingsView").then((module) => ({
16+
default: module.ApplicationSettingsView,
17+
}))
18+
);
19+
const AdvancedSettingsPage = React.lazy(() =>
20+
import("pages/SettingsPage/pages/AdvancedSettingsPage/AdvancedSettingsPage").then((module) => ({
21+
default: module.AdvancedSettingsPage,
22+
}))
23+
);
24+
25+
export const UserSettingsRoutes: React.FC = () => {
26+
return (
27+
<Routes>
28+
<Route element={<UserSettingsLayout />}>
29+
<Route path={SettingsRoutePaths.Account} element={<AccountSettingsView />} />
30+
<Route path={CloudSettingsRoutePaths.Applications} element={<ApplicationsView />} />
31+
<Route path={CloudSettingsRoutePaths.Advanced} element={<AdvancedSettingsPage />} />
32+
<Route path="*" element={<Navigate to={SettingsRoutePaths.Account} replace />} />
33+
</Route>
34+
</Routes>
35+
);
36+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
@use "scss/variables";
2+
@use "scss/colors";
3+
4+
.container {
5+
display: flex;
6+
gap: variables.$spacing-xl;
7+
height: 100%;
8+
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import React, { Suspense } from "react";
2+
import { useIntl } from "react-intl";
3+
import { Outlet } from "react-router-dom";
4+
5+
import { HeadTitle } from "components/HeadTitle";
6+
import LoadingPage from "components/LoadingPage";
7+
8+
import {
9+
SettingsButton,
10+
SettingsLink,
11+
SettingsNavigation,
12+
SettingsNavigationBlock,
13+
} from "area/settings/components/SettingsNavigation";
14+
import { useAuthService } from "core/services/auth";
15+
import { isOsanoActive, showOsanoDrawer } from "core/utils/dataPrivacy";
16+
import { useExperiment } from "hooks/services/Experiment";
17+
import { SettingsRoutePaths } from "pages/routePaths";
18+
19+
import { SettingsLayoutContent } from "./SettingsLayout";
20+
import styles from "./UserSettingsLayout.module.scss";
21+
22+
export const UserSettingsLayout: React.FC<React.PropsWithChildren> = () => {
23+
const { formatMessage } = useIntl();
24+
const { applicationSupport } = useAuthService();
25+
const showAdvancedSettings = useExperiment("settings.showAdvancedSettings");
26+
27+
return (
28+
<>
29+
<HeadTitle titles={[{ id: "sidebar.userSettings" }]} />
30+
<main className={styles.container}>
31+
<SettingsNavigation>
32+
<SettingsNavigationBlock title={formatMessage({ id: "settings.userSettings" })}>
33+
<SettingsLink
34+
iconType="user"
35+
name={formatMessage({ id: "settings.account" })}
36+
to={SettingsRoutePaths.Account}
37+
/>
38+
{applicationSupport !== "none" && (
39+
<SettingsLink
40+
iconType="grid"
41+
name={formatMessage({ id: "settings.applications" })}
42+
to={SettingsRoutePaths.Applications}
43+
/>
44+
)}
45+
{isOsanoActive() && (
46+
<SettingsButton
47+
iconType="parameters"
48+
onClick={() => showOsanoDrawer()}
49+
name={formatMessage({ id: "settings.cookiePreferences" })}
50+
/>
51+
)}
52+
{showAdvancedSettings && (
53+
<SettingsLink
54+
iconType="gear"
55+
name={formatMessage({ id: "settings.advanced" })}
56+
to={SettingsRoutePaths.Advanced}
57+
/>
58+
)}
59+
</SettingsNavigationBlock>
60+
</SettingsNavigation>
61+
<SettingsLayoutContent>
62+
<Suspense fallback={<LoadingPage />}>
63+
<Outlet />
64+
</Suspense>
65+
</SettingsLayoutContent>
66+
</main>
67+
</>
68+
);
69+
};

airbyte-webapp/src/packages/cloud/cloudRoutes.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ const CloudMainViewRoutes = () => {
6969

7070
{isOrgPickerEnabled ? (
7171
<Route element={<MainLayout />}>
72-
<Route path="account" element={<div>User Settings</div>} />
7372
<Route path={`${RoutePaths.Organization}/:organizationId/*`} element={<OrganizationRoutes />} />
7473
<Route path={`${RoutePaths.Workspaces}/:workspaceId/*`} element={<WorkspacesRoutes />} />
7574
</Route>

airbyte-webapp/src/packages/cloud/views/routes/WorkspacesRoutes.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Navigate, Route, Routes } from "react-router-dom";
33

44
import { EnterpriseSourcePage } from "components/source/enterpriseStubs/EnterpriseSourcePage";
55

6+
import { UserSettingsRoutes } from "area/settings/UserSettingsRoutes";
67
import { useCurrentWorkspace } from "core/api";
78
import { usePrefetchWorkspaceData } from "core/api/cloud";
89
import { useAnalyticsRegisterValues } from "core/services/analytics/useAnalyticsService";
@@ -18,7 +19,7 @@ import { AccountSettingsView } from "packages/cloud/views/users/AccountSettingsV
1819
import { ApplicationSettingsView } from "packages/cloud/views/users/ApplicationSettingsView/ApplicationSettingsView";
1920
import { WorkspaceSettingsView } from "packages/cloud/views/workspaces/WorkspaceSettingsView";
2021
import WorkspaceUsagePage from "packages/cloud/views/workspaces/WorkspaceUsagePage";
21-
import { RoutePaths, DestinationPaths, SourcePaths } from "pages/routePaths";
22+
import { RoutePaths, DestinationPaths, SourcePaths, SettingsRoutePaths } from "pages/routePaths";
2223
import AdvancedSettingsPage from "pages/SettingsPage/pages/AdvancedSettingsPage";
2324
import {
2425
SourcesPage as SettingsSourcesPage,
@@ -123,6 +124,7 @@ export const WorkspacesRoutes: React.FC = () => {
123124
<Route path="*" element={<Navigate to={CloudSettingsRoutePaths.Account} replace />} />
124125
</Route>
125126
<Route path={`${RoutePaths.ConnectorBuilder}/*`} element={<ConnectorBuilderRoutes />} />
127+
<Route path={`${SettingsRoutePaths.User}/*`} element={<UserSettingsRoutes />} />
126128
<Route path="*" element={<Navigate to={RoutePaths.Connections} replace />} />
127129
</Routes>
128130
);

airbyte-webapp/src/pages/organization/OrganizationRoutes.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from "react";
22
import { Navigate, Route, Routes } from "react-router-dom";
33

44
import { useCurrentOrganizationId } from "area/organization/utils";
5+
import { UserSettingsRoutes } from "area/settings/UserSettingsRoutes";
56
import { FeatureItem, useFeature } from "core/services/features";
67
import { Intent, useGeneratedIntent, useIntent } from "core/utils/rbac";
78
import { useExperiment } from "hooks/services/Experiment";
@@ -10,7 +11,7 @@ import { EmbeddedOnboardingPage } from "pages/embedded/EmbeddedOnboardingPage/Em
1011
import { GeneralOrganizationSettingsPage } from "pages/SettingsPage/pages/Organization/GeneralOrganizationSettingsPage";
1112
import { OrganizationMembersPage } from "pages/SettingsPage/pages/Organization/OrganizationMembersPage";
1213

13-
import { RoutePaths } from "../routePaths";
14+
import { RoutePaths, SettingsRoutePaths } from "../routePaths";
1415

1516
// Import organization-related components
1617
const WorkspacesPage = React.lazy(() => import("pages/workspaces"));
@@ -42,6 +43,7 @@ export const OrganizationRoutes: React.FC = () => {
4243
<Route path={CloudSettingsRoutePaths.OrganizationUsage} element={<OrganizationUsagePage />} />
4344
)}
4445
<Route path={RoutePaths.Settings} element={<GeneralOrganizationSettingsPage />} />
46+
<Route path={`${SettingsRoutePaths.User}/*`} element={<UserSettingsRoutes />} />
4547
<Route path="*" element={<Navigate to={defaultPath} replace />} />
4648
</Routes>
4749
);

0 commit comments

Comments
 (0)