- Notifications
You must be signed in to change notification settings - Fork928
feat: Add update user roles action#1361
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
32cba83
b167995
cabe385
b71ede5
d5e749f
1e99a04
46add41
16d1e7b
1e93bd2
82a60f8
9c0587e
c7c7b95
a01cb87
f402da0
9f47873
6cf12b5
16c3fe3
9bd6ca5
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import { ComponentMeta, Story } from "@storybook/react" | ||
import React from "react" | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. @BrunoQuaresma Just looking at merged PRs to learn - no action necessary here. Curious if there's a reason we're importing React given we're on version 17 instead ofsilencing the 'React must be in scope' warnings. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Good question, I think it is automatically added by an eslint role, but I'm not 100% sure. | ||
import { MockAdminRole, MockMemberRole, MockSiteRoles } from "../../testHelpers" | ||
import { RoleSelect, RoleSelectProps } from "./RoleSelect" | ||
export default { | ||
title: "components/RoleSelect", | ||
component: RoleSelect, | ||
} as ComponentMeta<typeof RoleSelect> | ||
const Template: Story<RoleSelectProps> = (args) => <RoleSelect {...args} /> | ||
export const Close = Template.bind({}) | ||
Close.args = { | ||
roles: MockSiteRoles, | ||
selectedRoles: [MockAdminRole, MockMemberRole], | ||
} | ||
export const Open = Template.bind({}) | ||
Open.args = { | ||
open: true, | ||
roles: MockSiteRoles, | ||
selectedRoles: [MockAdminRole, MockMemberRole], | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
import Checkbox from "@material-ui/core/Checkbox" | ||
import MenuItem from "@material-ui/core/MenuItem" | ||
import Select from "@material-ui/core/Select" | ||
import { makeStyles, Theme } from "@material-ui/core/styles" | ||
import React from "react" | ||
import { Role } from "../../api/typesGenerated" | ||
export const Language = { | ||
label: "Roles", | ||
} | ||
export interface RoleSelectProps { | ||
roles: Role[] | ||
selectedRoles: Role[] | ||
onChange: (roles: Role["name"][]) => void | ||
loading?: boolean | ||
open?: boolean | ||
} | ||
export const RoleSelect: React.FC<RoleSelectProps> = ({ roles, selectedRoles, loading, onChange, open }) => { | ||
const styles = useStyles() | ||
const value = selectedRoles.map((r) => r.name) | ||
const renderValue = () => selectedRoles.map((r) => r.display_name).join(", ") | ||
const sortedRoles = roles.sort((a, b) => a.display_name.localeCompare(b.display_name)) | ||
return ( | ||
<Select | ||
aria-label={Language.label} | ||
open={open} | ||
multiple | ||
value={value} | ||
renderValue={renderValue} | ||
variant="outlined" | ||
className={styles.select} | ||
onChange={(e) => { | ||
const { value } = e.target | ||
onChange(value as string[]) | ||
}} | ||
> | ||
{sortedRoles.map((r) => { | ||
const isChecked = selectedRoles.some((selectedRole) => selectedRole.name === r.name) | ||
return ( | ||
<MenuItem key={r.name} value={r.name} disabled={loading}> | ||
<Checkbox color="primary" checked={isChecked} /> {r.display_name} | ||
</MenuItem> | ||
) | ||
})} | ||
</Select> | ||
) | ||
} | ||
const useStyles = makeStyles((theme: Theme) => ({ | ||
select: { | ||
margin: 0, | ||
// Set a fixed width for the select. It avoids selects having different sizes | ||
// depending on how many roles they have selected. | ||
width: theme.spacing(25), | ||
}, | ||
})) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -8,18 +8,22 @@ export interface TableHeadersProps { | ||
hasMenu?: boolean | ||
} | ||
export constTableHeaderRow: React.FC = ({children }) => { | ||
BrunoQuaresma marked this conversation as resolved. Show resolvedHide resolvedUh oh!There was an error while loading.Please reload this page. | ||
const styles = useStyles() | ||
return <TableRow className={styles.root}>{children}</TableRow> | ||
} | ||
export const TableHeaders: React.FC<TableHeadersProps> = ({ columns, hasMenu }) => { | ||
return ( | ||
<TableHeaderRow> | ||
{columns.map((c, idx) => ( | ||
<TableCell key={idx} size="small"> | ||
{c} | ||
</TableCell> | ||
))} | ||
{/* 1% is a trick to make the table cell width fit the content */} | ||
{hasMenu && <TableCell width="1%" />} | ||
</TableHeaderRow> | ||
) | ||
} | ||
Uh oh!
There was an error while loading.Please reload this page.