Skip to content

Commit 8c419e7

Browse files
committed
wow
1 parent 3bd4dbe commit 8c419e7

File tree

9 files changed

+122
-50
lines changed

9 files changed

+122
-50
lines changed
Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,26 @@
1+
import type { Interpolation, Theme } from "@emotion/react";
12
import KeyboardDoubleArrowRightIcon from "@mui/icons-material/KeyboardDoubleArrowRight";
23
import Link from "@mui/material/Link";
34
import type { FC, ReactNode } from "react";
45
import { Link as RouterLink } from "react-router-dom";
56

67
interface BreadcrumbsProps {
78
children?: ReactNode;
9+
className?: string;
810
}
911

10-
export const Breadcrumbs: FC<BreadcrumbsProps> = ({ children }) => {
12+
export const Breadcrumbs: FC<BreadcrumbsProps> = ({ children, className }) => {
1113
return (
12-
<div css={{ display: "flex", flexDirection: "row", gap: 10, fontSize: 14 }}>
14+
<div
15+
className={className}
16+
css={{
17+
display: "flex",
18+
alignItems: "center",
19+
flexDirection: "row",
20+
gap: 10,
21+
fontSize: 14,
22+
}}
23+
>
1324
{children}
1425
</div>
1526
);
@@ -23,19 +34,8 @@ interface CrumbProps {
2334

2435
export const Crumb: FC<CrumbProps> = ({ active, href, children }) => {
2536
return (
26-
<div
27-
css={{
28-
display: "flex",
29-
flexDirection: "row",
30-
gap: 10,
31-
alignItems: "center",
32-
fontWeight: 600,
33-
"&:first-of-type .chevron": {
34-
display: "none",
35-
},
36-
}}
37-
>
38-
<div className="chevron" css={{ display: "inline-block", paddingTop: 3 }}>
37+
<div css={styles.crumb}>
38+
<div className="chevron">
3939
<KeyboardDoubleArrowRightIcon css={{ width: 14, height: 14 }} />
4040
</div>
4141
{href && !active ? (
@@ -49,13 +49,22 @@ export const Crumb: FC<CrumbProps> = ({ active, href, children }) => {
4949
);
5050
};
5151

52-
/* <Breadcrumbs>
53-
<Crumb href="/wibble">Wibble</Crumb>
54-
<Crumb href="/wibble/wobble">Wobble</Crumb>
55-
</Breadcrumbs>;
52+
const styles = {
53+
crumb: {
54+
display: "flex",
55+
alignItems: "center",
56+
flexDirection: "row",
57+
gap: 10,
58+
fontWeight: 600,
5659

60+
"&:first-of-type .chevron": {
61+
display: "none",
62+
},
5763

58-
<Breadcrumbs breadcrumbs={[
59-
{ href: "/wibble", children: "Wibble" },
60-
{ href: "/wibble/wobble", children: "Wobble" },
61-
]} />; */
64+
"& .chevron": {
65+
display: "inline-block",
66+
paddingTop: 3,
67+
height: "fit-content",
68+
},
69+
},
70+
} satisfies Record<string, Interpolation<Theme>>;

site/src/pages/ManagementSettingsPage/GroupsPage/GroupPage.tsx

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import type {
2525
} from "api/typesGenerated";
2626
import { ErrorAlert } from "components/Alert/ErrorAlert";
2727
import { AvatarData } from "components/AvatarData/AvatarData";
28+
import { Breadcrumbs, Crumb } from "components/Breadcrumbs/Breadcrumbs";
2829
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";
2930
import { EmptyState } from "components/EmptyState/EmptyState";
3031
import { displayError, displaySuccess } from "components/GlobalSnackbar/utils";
@@ -51,15 +52,17 @@ import { useMutation, useQuery, useQueryClient } from "react-query";
5152
import { Link as RouterLink, useNavigate, useParams } from "react-router-dom";
5253
import { isEveryoneGroup } from "utils/groups";
5354
import { pageTitle } from "utils/page";
55+
import { useOrganizationSettings } from "../ManagementSettingsLayout";
5456

5557
export const GroupPage: FC = () => {
56-
const { organization = "default", groupName } = useParams() as {
57-
organization?: string;
58+
const { organization } = useOrganizationSettings();
59+
const { organization: organizationName, groupName } = useParams() as {
60+
organization: string;
5861
groupName: string;
5962
};
6063
const queryClient = useQueryClient();
6164
const navigate = useNavigate();
62-
const groupQuery = useQuery(group(organization, groupName));
65+
const groupQuery = useQuery(group(organizationName, groupName));
6366
const groupData = groupQuery.data;
6467
const { data: permissions } = useQuery(
6568
groupData ? groupPermissions(groupData.id) : { enabled: false },
@@ -95,6 +98,12 @@ export const GroupPage: FC = () => {
9598
}
9699
const groupId = groupData.id;
97100

101+
if (!organization || !groupQuery.data) {
102+
return <EmptyState message="Group not found" />;
103+
}
104+
105+
const groupDisplayName = groupQuery.data.display_name || groupQuery.data.name;
106+
98107
return (
99108
<>
100109
{helmet}
@@ -103,11 +112,23 @@ export const GroupPage: FC = () => {
103112
alignItems="baseline"
104113
direction="row"
105114
justifyContent="space-between"
115+
css={{ paddingBottom: 32 }}
106116
>
107-
<SettingsHeader
108-
title={groupData?.display_name || groupData?.name}
109-
description="Manage members for this group."
110-
/>
117+
<Breadcrumbs>
118+
<Crumb>Organizations</Crumb>
119+
<Crumb href={`/organizations/${organizationName}`}>
120+
{organization.display_name || organization.name}
121+
</Crumb>
122+
<Crumb href={`/organizations/${organizationName}/groups`}>
123+
Groups
124+
</Crumb>
125+
<Crumb
126+
href={`/organizations/${organizationName}/groups/${groupName}`}
127+
active
128+
>
129+
{groupDisplayName}
130+
</Crumb>
131+
</Breadcrumbs>
111132
{canUpdateGroup && (
112133
<Stack direction="row" spacing={2}>
113134
<Button

site/src/pages/ManagementSettingsPage/GroupsPage/GroupSettingsPageView.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ import {
1818
} from "utils/formUtils";
1919
import { isEveryoneGroup } from "utils/groups";
2020
import * as Yup from "yup";
21+
import { useOrganizationSettings } from "../ManagementSettingsLayout";
22+
import { EmptyState } from "components/EmptyState/EmptyState";
23+
import { Breadcrumbs, Crumb } from "components/Breadcrumbs/Breadcrumbs";
2124

2225
type FormData = {
2326
name: string;
@@ -138,19 +141,42 @@ const GroupSettingsPageView: FC<SettingsGroupPageViewProps> = ({
138141
isLoading,
139142
isUpdating,
140143
}) => {
144+
const { organization } = useOrganizationSettings();
145+
141146
if (isLoading) {
142147
return <Loader />;
143148
}
144149

150+
if (!organization || !group) {
151+
return <EmptyState message="Group not found" />;
152+
}
153+
154+
console.log(group);
155+
145156
return (
146157
<>
147-
<ResourcePageHeader
148-
displayName={group!.display_name}
149-
name={group!.name}
150-
css={{ paddingTop: 8 }}
151-
/>
158+
<Breadcrumbs css={{ paddingBottom: 32 }}>
159+
<Crumb>Organizations</Crumb>
160+
<Crumb href={`/organizations/${organization.name}`}>
161+
{organization.display_name || organization.name}
162+
</Crumb>
163+
<Crumb href={`/organizations/${organization.name}/groups`}>
164+
Groups
165+
</Crumb>
166+
<Crumb
167+
href={`/organizations/${organization.name}/groups/${group.name}`}
168+
>
169+
{group.display_name || group.name}
170+
</Crumb>
171+
<Crumb
172+
href={`/organizations/${organization.name}/groups/${group.name}/settings`}
173+
active
174+
>
175+
Settings
176+
</Crumb>
177+
</Breadcrumbs>
152178
<UpdateGroupForm
153-
group={group!}
179+
group={group}
154180
onCancel={onCancel}
155181
errors={formErrors}
156182
isLoading={isUpdating}

site/src/pages/ManagementSettingsPage/GroupsPage/GroupsPage.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ export const GroupsPage: FC = () => {
8080
</Stack>
8181

8282
<GroupsPageView
83-
organization={organization}
8483
groups={groupsQuery.data}
8584
canCreateGroup={permissions.createGroup}
8685
isTemplateRBACEnabled={feats.template_rbac}

site/src/pages/ManagementSettingsPage/GroupsPage/GroupsPageView.tsx

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import TableCell from "@mui/material/TableCell";
1010
import TableContainer from "@mui/material/TableContainer";
1111
import TableHead from "@mui/material/TableHead";
1212
import TableRow from "@mui/material/TableRow";
13-
import type { Group, Organization } from "api/typesGenerated";
13+
import type { Group } from "api/typesGenerated";
1414
import { AvatarData } from "components/AvatarData/AvatarData";
1515
import { AvatarDataSkeleton } from "components/AvatarData/AvatarDataSkeleton";
1616
import { ChooseOne, Cond } from "components/Conditionals/ChooseOne";
@@ -28,14 +28,12 @@ import { Link as RouterLink, useNavigate } from "react-router-dom";
2828
import { docs } from "utils/docs";
2929

3030
export type GroupsPageViewProps = {
31-
organization: Organization;
3231
groups: Group[] | undefined;
3332
canCreateGroup: boolean;
3433
isTemplateRBACEnabled: boolean;
3534
};
3635

3736
export const GroupsPageView: FC<GroupsPageViewProps> = ({
38-
organization,
3937
groups,
4038
canCreateGroup,
4139
isTemplateRBACEnabled,

site/src/pages/ManagementSettingsPage/IdpSyncPage/IdpSyncPage.tsx

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { pageTitle } from "utils/page";
2020
import { useOrganizationSettings } from "../ManagementSettingsLayout";
2121
import { IdpSyncHelpTooltip } from "./IdpSyncHelpTooltip";
2222
import IdpSyncPageView from "./IdpSyncPageView";
23+
import { Breadcrumbs, Crumb } from "components/Breadcrumbs/Breadcrumbs";
2324

2425
export const IdpSyncPage: FC = () => {
2526
const { organization: organizationName } = useParams() as {
@@ -65,12 +66,17 @@ export const IdpSyncPage: FC = () => {
6566
alignItems="baseline"
6667
direction="row"
6768
justifyContent="space-between"
69+
css={{ paddingBottom: 32 }}
6870
>
69-
<SettingsHeader
70-
title="IdP Sync"
71-
description="Group and role sync mappings (configured using Coder CLI)."
72-
tooltip={<IdpSyncHelpTooltip />}
73-
/>
71+
<Breadcrumbs>
72+
<Crumb>Organizations</Crumb>
73+
<Crumb href={`/organizations/${organization}`}>
74+
{organization.display_name || organization.name}
75+
</Crumb>
76+
<Crumb href={`/organizations/${organization}/idp-sync`} active>
77+
IdP Sync
78+
</Crumb>
79+
</Breadcrumbs>
7480
<Button
7581
startIcon={<LaunchOutlined />}
7682
component="a"

site/src/pages/ManagementSettingsPage/ManagementSettingsLayout.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { RequirePermission } from "contexts/auth/RequirePermission";
88
import { useDashboard } from "modules/dashboard/useDashboard";
99
import { type FC, Suspense } from "react";
1010
import { useQuery } from "react-query";
11-
import { Outlet, useParams } from "react-router-dom";
11+
import { Navigate, useNavigate, Outlet, useParams } from "react-router-dom";
1212
import { DeploySettingsContext } from "../DeploySettingsPage/DeploySettingsLayout";
1313
import { Sidebar } from "./Sidebar";
1414

site/src/pages/ManagementSettingsPage/OrganizationProvisionersPage.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ const OrganizationProvisionersPage: FC = () => {
3838

3939
return (
4040
<OrganizationProvisionersPageView
41+
organization={organization}
4142
showPaywall={!entitlements.features.multiple_organizations.enabled}
4243
error={provisionersQuery.error}
4344
buildInfo={buildInfoQuery.data}

site/src/pages/ManagementSettingsPage/OrganizationProvisionersPageView.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import OpenInNewIcon from "@mui/icons-material/OpenInNew";
22
import Button from "@mui/material/Button";
33
import type {
44
BuildInfoResponse,
5+
Organization,
56
ProvisionerKey,
67
ProvisionerKeyDaemons,
78
} from "api/typesGenerated";
@@ -18,6 +19,8 @@ import { docs } from "utils/docs";
1819
import { useOrganizationSettings } from "./ManagementSettingsLayout";
1920

2021
interface OrganizationProvisionersPageViewProps {
22+
organization: Organization;
23+
2124
/** Determines if the paywall will be shown or not */
2225
showPaywall?: boolean;
2326

@@ -33,15 +36,24 @@ interface OrganizationProvisionersPageViewProps {
3336

3437
export const OrganizationProvisionersPageView: FC<
3538
OrganizationProvisionersPageViewProps
36-
> = ({ showPaywall, error, buildInfo, provisioners }) => {
39+
> = ({ organization, showPaywall, error, buildInfo, provisioners }) => {
3740
return (
38-
<div>
41+
<Stack>
3942
<Stack
4043
alignItems="baseline"
4144
direction="row"
4245
justifyContent="space-between"
46+
css={{ paddingBottom: 32 }}
4347
>
44-
<SettingsHeader title="Provisioners" />
48+
<Breadcrumbs>
49+
<Crumb>Organizations</Crumb>
50+
<Crumb href={`/organizations/${organization}`}>
51+
{organization.display_name || organization.name}
52+
</Crumb>
53+
<Crumb href={`/organizations/${organization}/members`} active>
54+
Members
55+
</Crumb>
56+
</Breadcrumbs>
4557
{!showPaywall && (
4658
<Button
4759
endIcon={<OpenInNewIcon />}
@@ -65,7 +77,7 @@ export const OrganizationProvisionersPageView: FC<
6577
) : (
6678
<ViewContent buildInfo={buildInfo} provisioners={provisioners} />
6779
)}
68-
</div>
80+
</Stack>
6981
);
7082
};
7183

0 commit comments

Comments
 (0)