Skip to content

Commit 0f9de62

Browse files
committed
a mostly nice org settings page
1 parent 5f84937 commit 0f9de62

File tree

18 files changed

+586
-172
lines changed

18 files changed

+586
-172
lines changed

site/src/api/api.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,17 @@ class ApiMethods {
513513
return response.data;
514514
};
515515

516+
updateOrganization = async (
517+
orgId: string,
518+
params: TypesGen.UpdateOrganizationRequest,
519+
) => {
520+
const response = await this.axios.patch<TypesGen.Organization>(
521+
`/api/v2/organizations/${orgId}`,
522+
params,
523+
);
524+
return response.data;
525+
};
526+
516527
deleteOrganization = async (orgId: string) => {
517528
await this.axios.delete<TypesGen.Organization>(
518529
`/api/v2/organizations/${orgId}`,

site/src/api/queries/organizations.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import type { QueryClient } from "react-query";
22
import { API } from "api/api";
3-
import type { CreateOrganizationRequest } from "api/typesGenerated";
3+
import type {
4+
CreateOrganizationRequest,
5+
UpdateOrganizationRequest,
6+
} from "api/typesGenerated";
47
import { meKey, myOrganizationsKey } from "./users";
58

69
export const createOrganization = (queryClient: QueryClient) => {
@@ -15,6 +18,23 @@ export const createOrganization = (queryClient: QueryClient) => {
1518
};
1619
};
1720

21+
interface UpdateOrganizationVariables {
22+
orgId: string;
23+
req: UpdateOrganizationRequest;
24+
}
25+
26+
export const updateOrganization = (queryClient: QueryClient) => {
27+
return {
28+
mutationFn: (variables: UpdateOrganizationVariables) =>
29+
API.updateOrganization(variables.orgId, variables.req),
30+
31+
onSuccess: async () => {
32+
await queryClient.invalidateQueries(meKey);
33+
await queryClient.invalidateQueries(myOrganizationsKey);
34+
},
35+
};
36+
};
37+
1838
export const deleteOrganization = (queryClient: QueryClient) => {
1939
return {
2040
mutationFn: (orgId: string) => API.deleteOrganization(orgId),

site/src/components/FormFooter/FormFooter.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export interface FormFooterStyles {
1414
}
1515

1616
export interface FormFooterProps {
17-
onCancel: () => void;
17+
onCancel?: () => void;
1818
isLoading: boolean;
1919
styles?: FormFooterStyles;
2020
submitLabel?: string;
@@ -45,15 +45,17 @@ export const FormFooter: FC<FormFooterProps> = ({
4545
>
4646
{submitLabel}
4747
</LoadingButton>
48-
<Button
49-
size="large"
50-
type="button"
51-
css={styles.button}
52-
onClick={onCancel}
53-
tabIndex={0}
54-
>
55-
{Language.cancelLabel}
56-
</Button>
48+
{onCancel && (
49+
<Button
50+
size="large"
51+
type="button"
52+
css={styles.button}
53+
onClick={onCancel}
54+
tabIndex={0}
55+
>
56+
{Language.cancelLabel}
57+
</Button>
58+
)}
5759
{extraActions}
5860
</div>
5961
);

site/src/components/Sidebar/Sidebar.tsx

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,29 @@ export const SidebarNavItem: FC<SidebarNavItemProps> = ({
7777
);
7878
};
7979

80+
interface SidebarNavSubItemProps {
81+
children?: ReactNode;
82+
href: string;
83+
}
84+
85+
export const SidebarNavSubItem: FC<SidebarNavSubItemProps> = ({
86+
children,
87+
href,
88+
}) => {
89+
const link = useClassName(classNames.subLink, []);
90+
const activeLink = useClassName(classNames.activeSubLink, []);
91+
92+
return (
93+
<NavLink
94+
end
95+
to={href}
96+
className={({ isActive }) => cx([link, isActive && activeLink])}
97+
>
98+
{children}
99+
</NavLink>
100+
);
101+
};
102+
80103
const styles = {
81104
sidebar: {
82105
width: 245,
@@ -118,22 +141,35 @@ const classNames = {
118141
&:hover {
119142
background-color: ${theme.palette.action.hover};
120143
}
144+
145+
border-left: 3px solid transparent;
121146
`,
122147

123148
activeLink: (css, theme) => css`
124-
background-color: ${theme.palette.action.hover};
125-
126-
&:before {
127-
content: "";
128-
display: block;
129-
width: 3px;
130-
height: 100%;
131-
position: absolute;
132-
left: 0;
133-
top: 0;
134-
background-color: ${theme.palette.primary.main};
135-
border-top-left-radius: 8px;
136-
border-bottom-left-radius: 8px;
149+
border-left-color: ${theme.palette.primary.main};
150+
`,
151+
152+
subLink: (css, theme) => css`
153+
color: inherit;
154+
text-decoration: none;
155+
156+
display: block;
157+
font-size: 13px;
158+
margin-left: 16px;
159+
padding: 8px;
160+
border-radius: 4px;
161+
transition: background-color 0.15s ease-in-out;
162+
margin-bottom: 1px;
163+
position: relative;
164+
border-left: 3px solid transparent;
165+
166+
&:hover {
167+
background-color: ${theme.palette.action.hover};
137168
}
138169
`,
170+
171+
activeSubLink: (css, theme) => css`
172+
border-left-color: ${theme.palette.primary.main};
173+
font-weight: 500;
174+
`,
139175
} satisfies Record<string, ClassName>;

site/src/modules/dashboard/Navbar/Navbar.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export const Navbar: FC = () => {
1212
const { metadata } = useEmbeddedMetadata();
1313
const buildInfoQuery = useQuery(buildInfo(metadata["build-info"]));
1414

15-
const { appearance } = useDashboard();
15+
const { appearance, experiments } = useDashboard();
1616
const { user: me, permissions, signOut } = useAuthenticated();
1717
const featureVisibility = useFeatureVisibility();
1818
const canViewAuditLog =
@@ -29,10 +29,11 @@ export const Navbar: FC = () => {
2929
buildInfo={buildInfoQuery.data}
3030
supportLinks={appearance.support_links}
3131
onSignOut={signOut}
32-
canViewAuditLog={canViewAuditLog}
3332
canViewDeployment={canViewDeployment}
33+
canViewOrganizations={experiments.includes("multi-organization")}
3434
canViewAllUsers={canViewAllUsers}
3535
canViewHealth={canViewHealth}
36+
canViewAuditLog={canViewAuditLog}
3637
proxyContextValue={proxyContextValue}
3738
/>
3839
);

site/src/modules/dashboard/Navbar/NavbarView.test.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ describe("NavbarView", () => {
2828
proxyContextValue={proxyContextValue}
2929
user={MockUser}
3030
onSignOut={noop}
31-
canViewAuditLog
3231
canViewDeployment
32+
canViewOrganizations
3333
canViewAllUsers
3434
canViewHealth
35+
canViewAuditLog
3536
/>,
3637
);
3738
const workspacesLink = await screen.findByText(navLanguage.workspaces);
@@ -44,10 +45,11 @@ describe("NavbarView", () => {
4445
proxyContextValue={proxyContextValue}
4546
user={MockUser}
4647
onSignOut={noop}
47-
canViewAuditLog
4848
canViewDeployment
49+
canViewOrganizations
4950
canViewAllUsers
5051
canViewHealth
52+
canViewAuditLog
5153
/>,
5254
);
5355
const templatesLink = await screen.findByText(navLanguage.templates);
@@ -60,10 +62,11 @@ describe("NavbarView", () => {
6062
proxyContextValue={proxyContextValue}
6163
user={MockUser}
6264
onSignOut={noop}
63-
canViewAuditLog
6465
canViewDeployment
66+
canViewOrganizations
6567
canViewAllUsers
6668
canViewHealth
69+
canViewAuditLog
6770
/>,
6871
);
6972
const deploymentMenu = await screen.findByText("Deployment");
@@ -78,10 +81,11 @@ describe("NavbarView", () => {
7881
proxyContextValue={proxyContextValue}
7982
user={MockUser}
8083
onSignOut={noop}
81-
canViewAuditLog
8284
canViewDeployment
85+
canViewOrganizations
8386
canViewAllUsers
8487
canViewHealth
88+
canViewAuditLog
8589
/>,
8690
);
8791
const deploymentMenu = await screen.findByText("Deployment");
@@ -96,10 +100,11 @@ describe("NavbarView", () => {
96100
proxyContextValue={proxyContextValue}
97101
user={MockUser}
98102
onSignOut={noop}
99-
canViewAuditLog
100103
canViewDeployment
104+
canViewOrganizations
101105
canViewAllUsers
102106
canViewHealth
107+
canViewAuditLog
103108
/>,
104109
);
105110
const deploymentMenu = await screen.findByText("Deployment");

site/src/modules/dashboard/Navbar/NavbarView.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,10 @@ export interface NavbarViewProps {
1919
buildInfo?: TypesGen.BuildInfoResponse;
2020
supportLinks?: readonly TypesGen.LinkConfig[];
2121
onSignOut: () => void;
22-
canViewAuditLog: boolean;
2322
canViewDeployment: boolean;
23+
canViewOrganizations: boolean;
2424
canViewAllUsers: boolean;
25+
canViewAuditLog: boolean;
2526
canViewHealth: boolean;
2627
proxyContextValue?: ProxyContextValue;
2728
}
@@ -69,10 +70,11 @@ export const NavbarView: FC<NavbarViewProps> = ({
6970
buildInfo,
7071
supportLinks,
7172
onSignOut,
72-
canViewAuditLog,
7373
canViewDeployment,
74+
canViewOrganizations,
7475
canViewAllUsers,
7576
canViewHealth,
77+
canViewAuditLog,
7678
proxyContextValue,
7779
}) => {
7880
const theme = useTheme();
@@ -134,7 +136,7 @@ export const NavbarView: FC<NavbarViewProps> = ({
134136

135137
<DeploymentDropdown
136138
canViewAuditLog={canViewAuditLog}
137-
canViewOrganizations
139+
canViewOrganizations={canViewOrganizations}
138140
canViewDeployment={canViewDeployment}
139141
canViewAllUsers={canViewAllUsers}
140142
canViewHealth={canViewHealth}

site/src/modules/dashboard/Navbar/UserDropdown/UserDropdown.tsx

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
import { css, type Interpolation, type Theme, useTheme } from "@emotion/react";
22
import Badge from "@mui/material/Badge";
33
import type { FC } from "react";
4-
import { useQuery } from "react-query";
5-
import { myOrganizations } from "api/queries/users";
64
import type * as TypesGen from "api/typesGenerated";
75
import { DropdownArrow } from "components/DropdownArrow/DropdownArrow";
86
import {
@@ -11,7 +9,6 @@ import {
119
PopoverTrigger,
1210
} from "components/Popover/Popover";
1311
import { UserAvatar } from "components/UserAvatar/UserAvatar";
14-
import { useDashboard } from "modules/dashboard/useDashboard";
1512
import { BUTTON_SM_HEIGHT, navHeight } from "theme/constants";
1613
import { UserDropdownContent } from "./UserDropdownContent";
1714

@@ -29,11 +26,6 @@ export const UserDropdown: FC<UserDropdownProps> = ({
2926
onSignOut,
3027
}) => {
3128
const theme = useTheme();
32-
const organizationsQuery = useQuery({
33-
...myOrganizations(),
34-
enabled: Boolean(localStorage.getItem("enableMultiOrganizationUi")),
35-
});
36-
const { organizationId, setOrganizationId } = useDashboard();
3729

3830
return (
3931
<Popover>
@@ -71,9 +63,6 @@ export const UserDropdown: FC<UserDropdownProps> = ({
7163
user={user}
7264
buildInfo={buildInfo}
7365
supportLinks={supportLinks}
74-
organizations={organizationsQuery.data}
75-
organizationId={organizationId}
76-
setOrganizationId={setOrganizationId}
7766
onSignOut={onSignOut}
7867
/>
7968
</PopoverContent>

site/src/modules/dashboard/Navbar/UserDropdown/UserDropdownContent.tsx

Lines changed: 0 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -29,19 +29,13 @@ export const Language = {
2929

3030
export interface UserDropdownContentProps {
3131
user: TypesGen.User;
32-
organizations?: TypesGen.Organization[];
33-
organizationId?: string;
34-
setOrganizationId?: (id: string) => void;
3532
buildInfo?: TypesGen.BuildInfoResponse;
3633
supportLinks?: readonly TypesGen.LinkConfig[];
3734
onSignOut: () => void;
3835
}
3936

4037
export const UserDropdownContent: FC<UserDropdownContentProps> = ({
4138
user,
42-
organizations,
43-
organizationId,
44-
setOrganizationId,
4539
buildInfo,
4640
supportLinks,
4741
onSignOut,
@@ -79,43 +73,6 @@ export const UserDropdownContent: FC<UserDropdownContentProps> = ({
7973

8074
<Divider css={{ marginBottom: 8 }} />
8175

82-
{organizations && (
83-
<>
84-
<div>
85-
<div
86-
css={{
87-
padding: "8px 20px 6px",
88-
textTransform: "uppercase",
89-
letterSpacing: 1.1,
90-
lineHeight: 1.1,
91-
fontSize: "0.8em",
92-
}}
93-
>
94-
My teams
95-
</div>
96-
{organizations.map((org) => (
97-
<MenuItem
98-
key={org.id}
99-
css={styles.menuItem}
100-
onClick={() => {
101-
setOrganizationId?.(org.id);
102-
popover.setIsOpen(false);
103-
}}
104-
>
105-
{/* <LogoutIcon css={styles.menuItemIcon} /> */}
106-
<Stack direction="row" spacing={1} css={styles.menuItemText}>
107-
{org.name}
108-
{organizationId === org.id && (
109-
<span css={{ fontSize: 12, color: "gray" }}>Current</span>
110-
)}
111-
</Stack>
112-
</MenuItem>
113-
))}
114-
</div>
115-
<Divider css={{ marginTop: 8, marginBottom: 8 }} />
116-
</>
117-
)}
118-
11976
<Link to="/settings/account" css={styles.link}>
12077
<MenuItem css={styles.menuItem} onClick={onPopoverClose}>
12178
<AccountIcon css={styles.menuItemIcon} />

0 commit comments

Comments
 (0)