Skip to content

feat: unify organization and deployment management settings #13602

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 17 commits into from
Jul 1, 2024
Prev Previous commit
Next Next commit
yay
  • Loading branch information
aslilac committed Jun 20, 2024
commit d532a2b5d21cafa9ead145381b5c90b125317b1c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Meta, StoryObj } from "@storybook/react";
import { CreateOrganizationPageView } from "./CreateOrganizationPageView";

const meta: Meta<typeof CreateOrganizationPageView> = {
title: "pages/CreateOrganizationPageView",
component: CreateOrganizationPageView,
};

export default meta;
type Story = StoryObj<typeof CreateOrganizationPageView>;

export const Example: Story = {};
88 changes: 88 additions & 0 deletions site/src/pages/ManagementSettingsPage/Horizontal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { type Interpolation, type Theme } from "@emotion/react";

Check failure on line 1 in site/src/pages/ManagementSettingsPage/Horizontal.tsx

View workflow job for this annotation

GitHub Actions / lint

TypeScript will only remove the inline type specifiers which will leave behind a side effect import at runtime. Convert this to a top-level type qualifier to properly remove the entire import

Check failure on line 1 in site/src/pages/ManagementSettingsPage/Horizontal.tsx

View workflow job for this annotation

GitHub Actions / lint

TypeScript will only remove the inline type specifiers which will leave behind a side effect import at runtime. Convert this to a top-level type qualifier to properly remove the entire import
import { type FC, type HTMLAttributes, type ReactNode } from "react";

Check failure on line 2 in site/src/pages/ManagementSettingsPage/Horizontal.tsx

View workflow job for this annotation

GitHub Actions / lint

TypeScript will only remove the inline type specifiers which will leave behind a side effect import at runtime. Convert this to a top-level type qualifier to properly remove the entire import

Check failure on line 2 in site/src/pages/ManagementSettingsPage/Horizontal.tsx

View workflow job for this annotation

GitHub Actions / lint

TypeScript will only remove the inline type specifiers which will leave behind a side effect import at runtime. Convert this to a top-level type qualifier to properly remove the entire import

export const HorizontalContainer: FC<HTMLAttributes<HTMLDivElement>> = ({
...attrs
}) => {
return <div css={styles.horizontalContainer} {...attrs} />;
};

interface HorizontalSectionProps
extends Omit<HTMLAttributes<HTMLElement>, "title"> {
title: ReactNode;
description: ReactNode;
children?: ReactNode;
}

export const HorizontalSection: FC<HorizontalSectionProps> = ({
children,
title,
description,
...attrs
}) => {
return (
<section css={styles.formSection} {...attrs}>
<div css={styles.formSectionInfo}>
<h2 css={styles.formSectionInfoTitle}>{title}</h2>
<div css={styles.formSectionInfoDescription}>{description}</div>
</div>

{children}
</section>
);
};

const styles = {
horizontalContainer: (theme) => ({
display: "flex",
flexDirection: "column",
gap: 80,

[theme.breakpoints.down("md")]: {
gap: 64,
},
}),

formSection: (theme) => ({
display: "flex",
flexDirection: "row",
gap: 120,

[theme.breakpoints.down("lg")]: {
flexDirection: "column",
gap: 16,
},
}),

formSectionInfo: (theme) => ({
width: "100%",
flexShrink: 0,
top: 24,
maxWidth: 312,
position: "sticky",

[theme.breakpoints.down("md")]: {
width: "100%",
position: "initial" as const,
},
}),

formSectionInfoTitle: (theme) => ({
fontSize: 20,
color: theme.palette.text.primary,
fontWeight: 400,
margin: 0,
marginBottom: 8,
display: "flex",
flexDirection: "row",
alignItems: "center",
gap: 12,
}),

formSectionInfoDescription: (theme) => ({
fontSize: 14,
color: theme.palette.text.secondary,
lineHeight: "160%",
margin: 0,
}),
} satisfies Record<string, Interpolation<Theme>>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Meta, StoryObj } from "@storybook/react";
import { OrganizationSettingsPageView } from "./OrganizationSettingsPageView";
import { MockOrganization } from "testHelpers/entities";

Check failure on line 3 in site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.stories.tsx

View workflow job for this annotation

GitHub Actions / lint

`testHelpers/entities` import should occur before import of `./OrganizationSettingsPageView`

Check failure on line 3 in site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.stories.tsx

View workflow job for this annotation

GitHub Actions / lint

`testHelpers/entities` import should occur before import of `./OrganizationSettingsPageView`

const meta: Meta<typeof OrganizationSettingsPageView> = {
title: "pages/OrganizationSettingsPageView",
component: OrganizationSettingsPageView,
args: {
org: MockOrganization,
},
};

export default meta;
type Story = StoryObj<typeof OrganizationSettingsPageView>;

export const Example: Story = {};
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import { useFormik } from "formik";
import type { FC } from "react";
import { type FC, useState } from "react";
import * as Yup from "yup";
import type {
Organization,
Expand All @@ -22,6 +22,8 @@
displayNameValidator,
onChangeTrimmed,
} from "utils/formUtils";
import { HorizontalContainer, HorizontalSection } from "./Horizontal";
import { DeleteDialog } from "components/Dialogs/DeleteDialog/DeleteDialog";

Check failure on line 26 in site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx

View workflow job for this annotation

GitHub Actions / lint

`components/Dialogs/DeleteDialog/DeleteDialog` import should occur before import of `components/Form/Form`

Check failure on line 26 in site/src/pages/ManagementSettingsPage/OrganizationSettingsPageView.tsx

View workflow job for this annotation

GitHub Actions / lint

`components/Dialogs/DeleteDialog/DeleteDialog` import should occur before import of `components/Form/Form`

const MAX_DESCRIPTION_CHAR_LIMIT = 128;
const MAX_DESCRIPTION_MESSAGE = `Please enter a description that is no longer than ${MAX_DESCRIPTION_CHAR_LIMIT} characters.`;
Expand Down Expand Up @@ -59,6 +61,8 @@
});
const getFieldHelpers = getFormHelpers(form, error);

const [isDeleting, setIsDeleting] = useState(false);

return (
<div>
<PageHeader>
Expand All @@ -70,7 +74,7 @@
aria-label="Organization settings form"
>
<FormSection
title="General info"
title="Info"
description="Change the name or description of the organization."
>
<fieldset
Expand Down Expand Up @@ -110,14 +114,59 @@
</HorizontalForm>

{!org.is_default && (
<Button
css={styles.dangerButton}
variant="contained"
onClick={onDeleteOrg}
>
Delete this organization
</Button>
<HorizontalContainer css={{ marginTop: 48 }}>
<HorizontalSection
title="Settings"
description="Change or delete your organization."
>
<div
css={(theme) => ({
display: "flex",
backgroundColor: theme.roles.danger.background,
alignItems: "center",
justifyContent: "space-between",
border: `1px solid ${theme.roles.danger.outline}`,
borderRadius: 8,
padding: 12,
paddingLeft: 18,
gap: 8,
lineHeight: "18px",
flexGrow: 1,

"& .option": {
color: theme.roles.danger.fill.solid,
"&.Mui-checked": {
color: theme.roles.danger.fill.solid,
},
},

"& .info": {
fontSize: 14,
fontWeight: 600,
color: theme.roles.danger.text,
},
})}
>
<span>Deleting an organization is irreversible.</span>
<Button
css={styles.dangerButton}
variant="contained"
onClick={() => setIsDeleting(true)}
>
Delete this organization
</Button>
</div>
</HorizontalSection>
</HorizontalContainer>
)}

<DeleteDialog
isOpen={isDeleting}
onConfirm={onDeleteOrg}
onCancel={() => setIsDeleting(false)}
entity="organization"
name={org.name}
/>
</div>
);
};
Expand Down
13 changes: 9 additions & 4 deletions site/src/testHelpers/entities.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ import type { TemplateVersionFiles } from "utils/templateVersion";

export const MockOrganization: TypesGen.Organization = {
id: "fc0774ce-cc9e-48d4-80ae-88f7a4d4a8b0",
name: "test-organization",
display_name: "Test Organization",
description: "",
icon: "",
name: "my-organization",
display_name: "My Organization",
description: "An organization that gets used for stuff.",
icon: "/emojis/1f957.png",
created_at: "",
updated_at: "",
is_default: false,
};

export const MockDefaultOrganization: TypesGen.Organization = {
...MockOrganization,
is_default: true,
};

Expand Down
Loading