forked from cerc-io/snowballtools-base
[7/n][project settings ui] member list cleanup (#40)
This commit is contained in:
commit
039753df56
@ -1,18 +1,15 @@
|
|||||||
import { useCallback, useState } from 'react';
|
import { useCallback, useState } from 'react';
|
||||||
import { Permission, User } from 'gql-client';
|
|
||||||
|
|
||||||
import {
|
|
||||||
Select,
|
|
||||||
Option,
|
|
||||||
Chip,
|
|
||||||
} from '@snowballtools/material-tailwind-react-fork';
|
|
||||||
|
|
||||||
import { formatAddress } from 'utils/format';
|
|
||||||
import { RemoveMemberDialog } from 'components/projects/Dialog/RemoveMemberDialog';
|
import { RemoveMemberDialog } from 'components/projects/Dialog/RemoveMemberDialog';
|
||||||
|
import { Select, SelectOption } from 'components/shared/Select';
|
||||||
|
import { LoaderIcon } from 'components/shared/CustomIcon';
|
||||||
import { Tooltip } from 'components/shared/Tooltip';
|
import { Tooltip } from 'components/shared/Tooltip';
|
||||||
import { Button } from 'components/shared/Button';
|
import { Button } from 'components/shared/Button';
|
||||||
|
import { Permission, User } from 'gql-client';
|
||||||
|
import { formatAddress } from 'utils/format';
|
||||||
|
import { Tag } from 'components/shared/Tag';
|
||||||
|
|
||||||
const PERMISSION_OPTIONS = [
|
const PERMISSION_OPTIONS: SelectOption[] = [
|
||||||
{
|
{
|
||||||
label: 'View only',
|
label: 'View only',
|
||||||
value: 'View',
|
value: 'View',
|
||||||
@ -23,7 +20,7 @@ const PERMISSION_OPTIONS = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const DROPDOWN_OPTIONS = [
|
const DROPDOWN_OPTIONS: SelectOption[] = [
|
||||||
...PERMISSION_OPTIONS,
|
...PERMISSION_OPTIONS,
|
||||||
{ label: 'Remove member', value: 'remove' },
|
{ label: 'Remove member', value: 'remove' },
|
||||||
];
|
];
|
||||||
@ -50,16 +47,21 @@ const MemberCard = ({
|
|||||||
onUpdateProjectMember,
|
onUpdateProjectMember,
|
||||||
}: MemberCardProps) => {
|
}: MemberCardProps) => {
|
||||||
const [ethAddress, emailDomain] = member.email.split('@');
|
const [ethAddress, emailDomain] = member.email.split('@');
|
||||||
const [selectedPermission, setSelectedPermission] = useState(
|
const [selectedPermission, setSelectedPermission] = useState<SelectOption>(
|
||||||
permissions.join('+'),
|
PERMISSION_OPTIONS.map((value) => {
|
||||||
|
permissions.join('+') === value.value;
|
||||||
|
}).pop() ?? {
|
||||||
|
label: 'View only',
|
||||||
|
value: 'View',
|
||||||
|
},
|
||||||
);
|
);
|
||||||
const [removeMemberDialogOpen, setRemoveMemberDialogOpen] = useState(false);
|
const [removeMemberDialogOpen, setRemoveMemberDialogOpen] = useState(false);
|
||||||
|
|
||||||
const handlePermissionChange = useCallback(
|
const handlePermissionChange = useCallback(
|
||||||
async (value: string) => {
|
async (value: SelectOption) => {
|
||||||
setSelectedPermission(value);
|
setSelectedPermission(value);
|
||||||
|
|
||||||
if (value === 'remove') {
|
if (value.value === 'remove') {
|
||||||
setRemoveMemberDialogOpen((prevVal) => !prevVal);
|
setRemoveMemberDialogOpen((prevVal) => !prevVal);
|
||||||
// To display updated label in next render
|
// To display updated label in next render
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -67,7 +69,7 @@ const MemberCard = ({
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
if (onUpdateProjectMember) {
|
if (onUpdateProjectMember) {
|
||||||
const permissions = value.split('+') as Permission[];
|
const permissions = value.value.split('+') as Permission[];
|
||||||
await onUpdateProjectMember({ permissions });
|
await onUpdateProjectMember({ permissions });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,34 +97,19 @@ const MemberCard = ({
|
|||||||
<div className="basis-1/2">
|
<div className="basis-1/2">
|
||||||
{!isPending ? (
|
{!isPending ? (
|
||||||
<Select
|
<Select
|
||||||
size="lg"
|
options={DROPDOWN_OPTIONS}
|
||||||
|
size="md"
|
||||||
label={isOwner ? 'Owner' : ''}
|
label={isOwner ? 'Owner' : ''}
|
||||||
disabled={isOwner}
|
disabled={isOwner}
|
||||||
value={selectedPermission}
|
value={selectedPermission}
|
||||||
onChange={(value) => handlePermissionChange(value!)}
|
onChange={(value) => handlePermissionChange(value as SelectOption)}
|
||||||
selected={(_, index) => (
|
/>
|
||||||
<span>{DROPDOWN_OPTIONS[index!]?.label}</span>
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{DROPDOWN_OPTIONS.map((permission, key) => (
|
|
||||||
<Option key={key} value={permission.value}>
|
|
||||||
^ {permission.label}
|
|
||||||
{permission.value === selectedPermission && (
|
|
||||||
<p className="float-right">^</p>
|
|
||||||
)}
|
|
||||||
</Option>
|
|
||||||
))}
|
|
||||||
</Select>
|
|
||||||
) : (
|
) : (
|
||||||
<div className="flex justify-end gap-2">
|
<div className="flex justify-end gap-2">
|
||||||
<div>
|
<div>
|
||||||
<Chip
|
<Tag type="positive" size="sm" leftIcon={<LoaderIcon />}>
|
||||||
value="Pending"
|
Pending
|
||||||
variant="outlined"
|
</Tag>
|
||||||
color="orange"
|
|
||||||
size="sm"
|
|
||||||
icon={'^'}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button
|
<Button
|
||||||
|
@ -0,0 +1,98 @@
|
|||||||
|
import { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
import { User } from 'gql-client';
|
||||||
|
import MemberCard from 'components/projects/project/settings/MemberCard';
|
||||||
|
|
||||||
|
const meta: Meta<typeof MemberCard> = {
|
||||||
|
title: 'Project/Settings/MemberCard',
|
||||||
|
component: MemberCard,
|
||||||
|
tags: ['autodocs'],
|
||||||
|
argTypes: {
|
||||||
|
member: {
|
||||||
|
control: 'object',
|
||||||
|
},
|
||||||
|
isFirstCard: {
|
||||||
|
control: 'boolean',
|
||||||
|
},
|
||||||
|
isOwner: {
|
||||||
|
control: 'boolean',
|
||||||
|
},
|
||||||
|
isPending: {
|
||||||
|
control: 'boolean',
|
||||||
|
},
|
||||||
|
permissions: {
|
||||||
|
control: 'object',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
} as Meta<typeof MemberCard>;
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
|
||||||
|
type Story = StoryObj<typeof MemberCard>;
|
||||||
|
|
||||||
|
const defaultUser = {
|
||||||
|
id: 'hellodsadass',
|
||||||
|
name: 'Vivian',
|
||||||
|
email: 'welcome@helloworld.com',
|
||||||
|
isVerified: true,
|
||||||
|
createdAt: 'blah',
|
||||||
|
updatedAt: 'blah',
|
||||||
|
gitHubToken: 'blah',
|
||||||
|
} as User;
|
||||||
|
|
||||||
|
export const Owner: Story = {
|
||||||
|
render: ({ member, isFirstCard, isOwner, isPending, permissions }) => (
|
||||||
|
<MemberCard
|
||||||
|
member={member}
|
||||||
|
isFirstCard={isFirstCard}
|
||||||
|
isOwner={isOwner}
|
||||||
|
isPending={isPending}
|
||||||
|
permissions={permissions}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
args: {
|
||||||
|
member: defaultUser,
|
||||||
|
isFirstCard: true,
|
||||||
|
isOwner: true,
|
||||||
|
isPending: false,
|
||||||
|
permissions: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewPlusEditMember: Story = {
|
||||||
|
render: ({ member, isFirstCard, isOwner, isPending, permissions }) => (
|
||||||
|
<MemberCard
|
||||||
|
member={member}
|
||||||
|
isFirstCard={isFirstCard}
|
||||||
|
isOwner={isOwner}
|
||||||
|
isPending={isPending}
|
||||||
|
permissions={permissions}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
args: {
|
||||||
|
member: defaultUser,
|
||||||
|
isFirstCard: true,
|
||||||
|
isOwner: false,
|
||||||
|
isPending: false,
|
||||||
|
permissions: ['View+Edit'],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ViewMember: Story = {
|
||||||
|
render: ({ member, isFirstCard, isOwner, isPending, permissions }) => (
|
||||||
|
<MemberCard
|
||||||
|
member={member}
|
||||||
|
isFirstCard={isFirstCard}
|
||||||
|
isOwner={isOwner}
|
||||||
|
isPending={isPending}
|
||||||
|
permissions={permissions}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
args: {
|
||||||
|
member: defaultUser,
|
||||||
|
isFirstCard: true,
|
||||||
|
isOwner: false,
|
||||||
|
isPending: false,
|
||||||
|
permissions: ['View'],
|
||||||
|
},
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user