feat: redesign project sharing
This commit is contained in:
@ -3,32 +3,11 @@ import updateApolloCache from 'shared/utils/cache';
|
||||
import { usePopup, Popup } from 'shared/components/PopupMenu';
|
||||
import produce from 'immer';
|
||||
import {
|
||||
useUpdateProjectMemberRoleMutation,
|
||||
useCreateProjectMemberMutation,
|
||||
useDeleteProjectMemberMutation,
|
||||
useSetTaskCompleteMutation,
|
||||
useToggleTaskLabelMutation,
|
||||
useUpdateProjectNameMutation,
|
||||
useFindProjectQuery,
|
||||
useUpdateTaskGroupNameMutation,
|
||||
useUpdateTaskNameMutation,
|
||||
useUpdateProjectLabelMutation,
|
||||
useCreateTaskMutation,
|
||||
useDeleteProjectLabelMutation,
|
||||
useDeleteTaskMutation,
|
||||
useUpdateTaskLocationMutation,
|
||||
useUpdateTaskGroupLocationMutation,
|
||||
useCreateTaskGroupMutation,
|
||||
useDeleteTaskGroupMutation,
|
||||
useUpdateTaskDescriptionMutation,
|
||||
useAssignTaskMutation,
|
||||
DeleteTaskDocument,
|
||||
FindProjectDocument,
|
||||
useCreateProjectLabelMutation,
|
||||
useUnassignTaskMutation,
|
||||
useUpdateTaskDueDateMutation,
|
||||
FindProjectQuery,
|
||||
useUsersQuery,
|
||||
} from 'shared/generated/graphql';
|
||||
import LabelManager from 'shared/components/PopupMenu/LabelManager';
|
||||
import LabelEditor from 'shared/components/PopupMenu/LabelEditor';
|
||||
|
@ -16,7 +16,7 @@ import {
|
||||
} from 'react-router-dom';
|
||||
import {
|
||||
useUpdateProjectMemberRoleMutation,
|
||||
useCreateProjectMemberMutation,
|
||||
useInviteProjectMemberMutation,
|
||||
useDeleteProjectMemberMutation,
|
||||
useToggleTaskLabelMutation,
|
||||
useUpdateProjectNameMutation,
|
||||
@ -38,10 +38,12 @@ import Input from 'shared/components/Input';
|
||||
import Member from 'shared/components/Member';
|
||||
import EmptyBoard from 'shared/components/EmptyBoard';
|
||||
import NOOP from 'shared/utils/noop';
|
||||
import { Lock } from 'shared/icons';
|
||||
import { Lock, Cross } from 'shared/icons';
|
||||
import Button from 'shared/components/Button';
|
||||
import { useApolloClient } from '@apollo/react-hooks';
|
||||
import TaskAssignee from 'shared/components/TaskAssignee';
|
||||
import gql from 'graphql-tag';
|
||||
import { colourStyles } from 'shared/components/Select';
|
||||
import Board, { BoardLoading } from './Board';
|
||||
import Details from './Details';
|
||||
import LabelManagerEditor from './LabelManagerEditor';
|
||||
@ -77,10 +79,14 @@ const MemberList = styled.div`
|
||||
margin: 8px 0;
|
||||
`;
|
||||
|
||||
type InviteUserData = {
|
||||
email?: string;
|
||||
suerID?: string;
|
||||
};
|
||||
type UserManagementPopupProps = {
|
||||
users: Array<User>;
|
||||
projectMembers: Array<TaskUser>;
|
||||
onAddProjectMember: (userID: string) => void;
|
||||
onInviteProjectMember: (data: InviteUserData) => void;
|
||||
};
|
||||
|
||||
const VisibiltyPrivateIcon = styled(Lock)`
|
||||
@ -133,40 +139,182 @@ const fetchMembers = async (client: any, options: MemberFilterOptions, input: st
|
||||
query: gql`
|
||||
query {
|
||||
searchMembers(input: {SearchFilter:"${input}"}) {
|
||||
id
|
||||
similarity
|
||||
username
|
||||
fullName
|
||||
confirmed
|
||||
joined
|
||||
user {
|
||||
id
|
||||
fullName
|
||||
email
|
||||
profileIcon {
|
||||
url
|
||||
initials
|
||||
bgColor
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
});
|
||||
|
||||
let results: any = [];
|
||||
const emails: Array<string> = [];
|
||||
if (res.data && res.data.searchMembers) {
|
||||
results = [...res.data.searchMembers.map((m: any) => ({ label: m.fullName, value: m.id }))];
|
||||
results = [
|
||||
...res.data.searchMembers.map((m: any) => {
|
||||
emails.push(m.user.email);
|
||||
return {
|
||||
label: m.user.fullName,
|
||||
value: { id: m.id, type: 0, profileIcon: m.user.profileIcon },
|
||||
};
|
||||
}),
|
||||
];
|
||||
}
|
||||
|
||||
if (RFC2822_EMAIL.test(input)) {
|
||||
results = [...results, { label: input, value: input }];
|
||||
if (RFC2822_EMAIL.test(input) && !emails.find(e => e === input)) {
|
||||
results = [
|
||||
...results,
|
||||
{
|
||||
label: input,
|
||||
value: {
|
||||
id: input,
|
||||
type: 1,
|
||||
profileIcon: {
|
||||
bgColor: '#ccc',
|
||||
initials: input.charAt(0),
|
||||
},
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
return results;
|
||||
};
|
||||
|
||||
const UserManagementPopup: React.FC<UserManagementPopupProps> = ({ users, projectMembers, onAddProjectMember }) => {
|
||||
type UserOptionProps = {
|
||||
innerProps: any;
|
||||
isDisabled: boolean;
|
||||
isFocused: boolean;
|
||||
label: string;
|
||||
data: any;
|
||||
getValue: any;
|
||||
};
|
||||
|
||||
const OptionWrapper = styled.div<{ isFocused: boolean }>`
|
||||
cursor: pointer;
|
||||
padding: 4px 8px;
|
||||
${props => props.isFocused && `background: rgba(${props.theme.colors.primary});`}
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
const OptionContent = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-left: 12px;
|
||||
`;
|
||||
|
||||
const UserOption: React.FC<UserOptionProps> = ({ isDisabled, isFocused, innerProps, label, data }) => {
|
||||
return !isDisabled ? (
|
||||
<OptionWrapper {...innerProps} isFocused={isFocused}>
|
||||
<TaskAssignee
|
||||
size={32}
|
||||
member={{
|
||||
id: '',
|
||||
fullName: 'Jordan Knott',
|
||||
profileIcon: data.value.profileIcon,
|
||||
}}
|
||||
/>
|
||||
<OptionContent>{label}</OptionContent>
|
||||
</OptionWrapper>
|
||||
) : null;
|
||||
};
|
||||
|
||||
const OptionValueWrapper = styled.div`
|
||||
background: rgba(${props => props.theme.colors.bg.primary});
|
||||
border-radius: 4px;
|
||||
margin: 2px;
|
||||
padding: 3px 6px 3px 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const OptionValueLabel = styled.span`
|
||||
font-size: 12px;
|
||||
color: rgba(${props => props.theme.colors.text.secondary});
|
||||
`;
|
||||
|
||||
const OptionValueRemove = styled.button`
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
margin-left: 4px;
|
||||
`;
|
||||
const OptionValue = ({ data, removeProps }: any) => {
|
||||
return (
|
||||
<OptionValueWrapper>
|
||||
<OptionValueLabel>{data.label}</OptionValueLabel>
|
||||
<OptionValueRemove {...removeProps}>
|
||||
<Cross width={14} height={14} />
|
||||
</OptionValueRemove>
|
||||
</OptionValueWrapper>
|
||||
);
|
||||
};
|
||||
|
||||
const InviteButton = styled(Button)`
|
||||
margin-top: 12px;
|
||||
height: 32px;
|
||||
padding: 4px 12px;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
`;
|
||||
|
||||
const InviteContainer = styled.div`
|
||||
min-height: 300px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
`;
|
||||
|
||||
const UserManagementPopup: React.FC<UserManagementPopupProps> = ({ users, projectMembers, onInviteProjectMember }) => {
|
||||
const client = useApolloClient();
|
||||
const [invitedUsers, setInvitedUsers] = useState<Array<any> | null>(null);
|
||||
return (
|
||||
<Popup tab={0} title="Invite a user">
|
||||
<AsyncSelect isMulti cacheOptions defaultOption loadOptions={(i, cb) => fetchMembers(client, {}, i, cb)} />
|
||||
<ShareActions>
|
||||
<VisibiltyButton>
|
||||
<VisibiltyPrivateIcon width={12} height={12} />
|
||||
<VisibiltyButtonText>Private</VisibiltyButtonText>
|
||||
</VisibiltyButton>
|
||||
</ShareActions>
|
||||
<InviteContainer>
|
||||
<AsyncSelect
|
||||
placeholder="Email address or username"
|
||||
noOptionsMessage={() => null}
|
||||
onChange={(e: any) => setInvitedUsers(e ? e.value : null)}
|
||||
isMulti
|
||||
autoFocus
|
||||
cacheOptions
|
||||
styles={colourStyles}
|
||||
defaultOption
|
||||
components={{
|
||||
MultiValue: OptionValue,
|
||||
Option: UserOption,
|
||||
IndicatorSeparator: null,
|
||||
DropdownIndicator: null,
|
||||
}}
|
||||
loadOptions={(i, cb) => fetchMembers(client, {}, i, cb)}
|
||||
/>
|
||||
</InviteContainer>
|
||||
<InviteButton
|
||||
onClick={() => {
|
||||
// FUCK, gotta rewrite invite member to be MULTIPLE. SHIT!
|
||||
// onInviteProjectMember();
|
||||
}}
|
||||
disabled={invitedUsers === null}
|
||||
hoverVariant="none"
|
||||
fontSize="16px"
|
||||
>
|
||||
Send Invite
|
||||
</InviteButton>
|
||||
</Popup>
|
||||
);
|
||||
};
|
||||
@ -250,14 +398,14 @@ const Project = () => {
|
||||
},
|
||||
});
|
||||
|
||||
const [createProjectMember] = useCreateProjectMemberMutation({
|
||||
const [inviteProjectMember] = useInviteProjectMemberMutation({
|
||||
update: (client, response) => {
|
||||
updateApolloCache<FindProjectQuery>(
|
||||
client,
|
||||
FindProjectDocument,
|
||||
cache =>
|
||||
produce(cache, draftCache => {
|
||||
draftCache.findProject.members.push({ ...response.data.createProjectMember.member });
|
||||
draftCache.findProject.members.push({ ...response.data.inviteProjectMember.member });
|
||||
}),
|
||||
{ projectID },
|
||||
);
|
||||
@ -324,8 +472,8 @@ const Project = () => {
|
||||
showPopup(
|
||||
$target,
|
||||
<UserManagementPopup
|
||||
onAddProjectMember={userID => {
|
||||
createProjectMember({ variables: { userID, projectID } });
|
||||
onInviteProjectMember={userID => {
|
||||
// /inviteProjectMember({ variables: { userID, projectID } });
|
||||
}}
|
||||
users={data.users}
|
||||
projectMembers={data.findProject.members}
|
||||
|
@ -35,11 +35,15 @@ const Base = styled.button<{ color: string; disabled: boolean }>`
|
||||
`}
|
||||
`;
|
||||
|
||||
const Filled = styled(Base)`
|
||||
const Filled = styled(Base)<{ hoverVariant: HoverVariant }>`
|
||||
background: rgba(${props => props.theme.colors[props.color]});
|
||||
&:hover {
|
||||
box-shadow: 0 8px 25px -8px rgba(${props => props.theme.colors[props.color]});
|
||||
}
|
||||
${props =>
|
||||
props.hoverVariant === 'boxShadow' &&
|
||||
css`
|
||||
&:hover {
|
||||
box-shadow: 0 8px 25px -8px rgba(${props.theme.colors[props.color]});
|
||||
}
|
||||
`}
|
||||
`;
|
||||
const Outline = styled(Base)<{ invert: boolean }>`
|
||||
border: 1px solid rgba(${props => props.theme.colors[props.color]});
|
||||
@ -123,9 +127,11 @@ const Relief = styled(Base)`
|
||||
}
|
||||
`;
|
||||
|
||||
type HoverVariant = 'boxShadow' | 'none';
|
||||
type ButtonProps = {
|
||||
fontSize?: string;
|
||||
variant?: 'filled' | 'outline' | 'flat' | 'lineDown' | 'gradient' | 'relief';
|
||||
hoverVariant?: HoverVariant;
|
||||
color?: 'primary' | 'danger' | 'success' | 'warning' | 'dark';
|
||||
disabled?: boolean;
|
||||
type?: 'button' | 'submit';
|
||||
@ -142,6 +148,7 @@ const Button: React.FC<ButtonProps> = ({
|
||||
invert = false,
|
||||
color = 'primary',
|
||||
variant = 'filled',
|
||||
hoverVariant = 'boxShadow',
|
||||
type = 'button',
|
||||
justifyTextContent = 'center',
|
||||
icon,
|
||||
@ -158,7 +165,15 @@ const Button: React.FC<ButtonProps> = ({
|
||||
switch (variant) {
|
||||
case 'filled':
|
||||
return (
|
||||
<Filled ref={$button} type={type} onClick={handleClick} className={className} disabled={disabled} color={color}>
|
||||
<Filled
|
||||
ref={$button}
|
||||
hoverVariant={hoverVariant}
|
||||
type={type}
|
||||
onClick={handleClick}
|
||||
className={className}
|
||||
disabled={disabled}
|
||||
color={color}
|
||||
>
|
||||
{icon && icon}
|
||||
<Text hasIcon={typeof icon !== 'undefined'} justifyTextContent={justifyTextContent} fontSize={fontSize}>
|
||||
{children}
|
||||
|
@ -16,7 +16,7 @@ function getBackgroundColor(isDisabled: boolean, isSelected: boolean, isFocused:
|
||||
return null;
|
||||
}
|
||||
|
||||
const colourStyles = {
|
||||
export const colourStyles = {
|
||||
control: (styles: any, data: any) => {
|
||||
return {
|
||||
...styles,
|
||||
|
@ -1,5 +1,5 @@
|
||||
import React, { useRef } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import styled, { css } from 'styled-components';
|
||||
import { DoubleChevronUp, Crown } from 'shared/icons';
|
||||
|
||||
export const AdminIcon = styled(DoubleChevronUp)`
|
||||
@ -24,7 +24,12 @@ const TaskDetailAssignee = styled.div`
|
||||
position: relative;
|
||||
`;
|
||||
|
||||
export const Wrapper = styled.div<{ size: number | string; bgColor: string | null; backgroundURL: string | null }>`
|
||||
export const Wrapper = styled.div<{
|
||||
size: number | string;
|
||||
bgColor: string | null;
|
||||
backgroundURL: string | null;
|
||||
hasClick: boolean;
|
||||
}>`
|
||||
width: ${props => props.size}px;
|
||||
height: ${props => props.size}px;
|
||||
border-radius: 9999px;
|
||||
@ -37,33 +42,52 @@ export const Wrapper = styled.div<{ size: number | string; bgColor: string | nul
|
||||
background-size: contain;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
${props =>
|
||||
props.hasClick &&
|
||||
css`
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
`}
|
||||
`;
|
||||
|
||||
type TaskAssigneeProps = {
|
||||
size: number | string;
|
||||
showRoleIcons?: boolean;
|
||||
member: TaskUser;
|
||||
onMemberProfile: ($targetRef: React.RefObject<HTMLElement>, memberID: string) => void;
|
||||
onMemberProfile?: ($targetRef: React.RefObject<HTMLElement>, memberID: string) => void;
|
||||
className?: string;
|
||||
};
|
||||
|
||||
const TaskAssignee: React.FC<TaskAssigneeProps> = ({ showRoleIcons, member, onMemberProfile, size, className }) => {
|
||||
const $memberRef = useRef<HTMLDivElement>(null);
|
||||
let profileIcon: ProfileIcon = {
|
||||
url: null,
|
||||
bgColor: null,
|
||||
initials: null,
|
||||
};
|
||||
if (member.profileIcon) {
|
||||
profileIcon = member.profileIcon;
|
||||
}
|
||||
return (
|
||||
<TaskDetailAssignee
|
||||
className={className}
|
||||
ref={$memberRef}
|
||||
onClick={e => {
|
||||
e.stopPropagation();
|
||||
onMemberProfile($memberRef, member.id);
|
||||
if (onMemberProfile) {
|
||||
onMemberProfile($memberRef, member.id);
|
||||
}
|
||||
}}
|
||||
key={member.id}
|
||||
>
|
||||
<Wrapper backgroundURL={member.profileIcon.url ?? null} bgColor={member.profileIcon.bgColor ?? null} size={size}>
|
||||
{(!member.profileIcon.url && member.profileIcon.initials) ?? ''}
|
||||
<Wrapper
|
||||
hasClick={typeof onMemberProfile !== undefined}
|
||||
backgroundURL={profileIcon.url ?? null}
|
||||
bgColor={profileIcon.bgColor ?? null}
|
||||
size={size}
|
||||
>
|
||||
{(!profileIcon.url && profileIcon.initials) ?? ''}
|
||||
</Wrapper>
|
||||
{showRoleIcons && member.role && member.role.code === 'admin' && <AdminIcon width={10} height={10} />}
|
||||
{showRoleIcons && member.role && member.role.code === 'owner' && <OwnerIcon width={10} height={10} />}
|
||||
|
@ -226,6 +226,7 @@ export type Query = {
|
||||
notifications: Array<Notification>;
|
||||
organizations: Array<Organization>;
|
||||
projects: Array<Project>;
|
||||
searchMembers: Array<MemberSearchResult>;
|
||||
taskGroups: Array<TaskGroup>;
|
||||
teams: Array<Team>;
|
||||
users: Array<UserAccount>;
|
||||
@ -256,6 +257,11 @@ export type QueryProjectsArgs = {
|
||||
input?: Maybe<ProjectsFilter>;
|
||||
};
|
||||
|
||||
|
||||
export type QuerySearchMembersArgs = {
|
||||
input: MemberSearchFilter;
|
||||
};
|
||||
|
||||
export type Mutation = {
|
||||
__typename?: 'Mutation';
|
||||
addTaskLabel: Task;
|
||||
@ -263,7 +269,6 @@ export type Mutation = {
|
||||
clearProfileAvatar: UserAccount;
|
||||
createProject: Project;
|
||||
createProjectLabel: ProjectLabel;
|
||||
createProjectMember: CreateProjectMemberPayload;
|
||||
createRefreshToken: RefreshToken;
|
||||
createTask: Task;
|
||||
createTaskChecklist: TaskChecklist;
|
||||
@ -284,6 +289,7 @@ export type Mutation = {
|
||||
deleteTeamMember: DeleteTeamMemberPayload;
|
||||
deleteUserAccount: DeleteUserAccountPayload;
|
||||
duplicateTaskGroup: DuplicateTaskGroupPayload;
|
||||
inviteProjectMember: InviteProjectMemberPayload;
|
||||
logoutUser: Scalars['Boolean'];
|
||||
removeTaskLabel: Task;
|
||||
setTaskChecklistItemComplete: TaskChecklistItem;
|
||||
@ -333,11 +339,6 @@ export type MutationCreateProjectLabelArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateProjectMemberArgs = {
|
||||
input: CreateProjectMember;
|
||||
};
|
||||
|
||||
|
||||
export type MutationCreateRefreshTokenArgs = {
|
||||
input: NewRefreshToken;
|
||||
};
|
||||
@ -438,6 +439,11 @@ export type MutationDuplicateTaskGroupArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationInviteProjectMemberArgs = {
|
||||
input: InviteProjectMember;
|
||||
};
|
||||
|
||||
|
||||
export type MutationLogoutUserArgs = {
|
||||
input: LogoutUser;
|
||||
};
|
||||
@ -688,13 +694,14 @@ export type UpdateProjectLabelColor = {
|
||||
labelColorID: Scalars['UUID'];
|
||||
};
|
||||
|
||||
export type CreateProjectMember = {
|
||||
export type InviteProjectMember = {
|
||||
projectID: Scalars['UUID'];
|
||||
userID: Scalars['UUID'];
|
||||
userID?: Maybe<Scalars['UUID']>;
|
||||
email?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
export type CreateProjectMemberPayload = {
|
||||
__typename?: 'CreateProjectMemberPayload';
|
||||
export type InviteProjectMemberPayload = {
|
||||
__typename?: 'InviteProjectMemberPayload';
|
||||
ok: Scalars['Boolean'];
|
||||
member: Member;
|
||||
};
|
||||
@ -989,6 +996,20 @@ export type UpdateTeamMemberRolePayload = {
|
||||
member: Member;
|
||||
};
|
||||
|
||||
export type MemberSearchFilter = {
|
||||
SearchFilter: Scalars['String'];
|
||||
projectID?: Maybe<Scalars['UUID']>;
|
||||
};
|
||||
|
||||
export type MemberSearchResult = {
|
||||
__typename?: 'MemberSearchResult';
|
||||
similarity: Scalars['Int'];
|
||||
user: UserAccount;
|
||||
confirmed: Scalars['Boolean'];
|
||||
invited: Scalars['Boolean'];
|
||||
joined: Scalars['Boolean'];
|
||||
};
|
||||
|
||||
export type UpdateUserInfoPayload = {
|
||||
__typename?: 'UpdateUserInfoPayload';
|
||||
user: UserAccount;
|
||||
@ -1390,31 +1411,6 @@ export type MeQuery = (
|
||||
) }
|
||||
);
|
||||
|
||||
export type CreateProjectMemberMutationVariables = {
|
||||
projectID: Scalars['UUID'];
|
||||
userID: Scalars['UUID'];
|
||||
};
|
||||
|
||||
|
||||
export type CreateProjectMemberMutation = (
|
||||
{ __typename?: 'Mutation' }
|
||||
& { createProjectMember: (
|
||||
{ __typename?: 'CreateProjectMemberPayload' }
|
||||
& Pick<CreateProjectMemberPayload, 'ok'>
|
||||
& { member: (
|
||||
{ __typename?: 'Member' }
|
||||
& Pick<Member, 'id' | 'fullName' | 'username'>
|
||||
& { profileIcon: (
|
||||
{ __typename?: 'ProfileIcon' }
|
||||
& Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
|
||||
), role: (
|
||||
{ __typename?: 'Role' }
|
||||
& Pick<Role, 'code' | 'name'>
|
||||
) }
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
||||
export type DeleteProjectMutationVariables = {
|
||||
projectID: Scalars['UUID'];
|
||||
};
|
||||
@ -1450,6 +1446,32 @@ export type DeleteProjectMemberMutation = (
|
||||
) }
|
||||
);
|
||||
|
||||
export type InviteProjectMemberMutationVariables = {
|
||||
projectID: Scalars['UUID'];
|
||||
userID?: Maybe<Scalars['UUID']>;
|
||||
email?: Maybe<Scalars['String']>;
|
||||
};
|
||||
|
||||
|
||||
export type InviteProjectMemberMutation = (
|
||||
{ __typename?: 'Mutation' }
|
||||
& { inviteProjectMember: (
|
||||
{ __typename?: 'InviteProjectMemberPayload' }
|
||||
& Pick<InviteProjectMemberPayload, 'ok'>
|
||||
& { member: (
|
||||
{ __typename?: 'Member' }
|
||||
& Pick<Member, 'id' | 'fullName' | 'username'>
|
||||
& { profileIcon: (
|
||||
{ __typename?: 'ProfileIcon' }
|
||||
& Pick<ProfileIcon, 'url' | 'initials' | 'bgColor'>
|
||||
), role: (
|
||||
{ __typename?: 'Role' }
|
||||
& Pick<Role, 'code' | 'name'>
|
||||
) }
|
||||
) }
|
||||
) }
|
||||
);
|
||||
|
||||
export type UpdateProjectMemberRoleMutationVariables = {
|
||||
projectID: Scalars['UUID'];
|
||||
userID: Scalars['UUID'];
|
||||
@ -2884,53 +2906,6 @@ export function useMeLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptio
|
||||
export type MeQueryHookResult = ReturnType<typeof useMeQuery>;
|
||||
export type MeLazyQueryHookResult = ReturnType<typeof useMeLazyQuery>;
|
||||
export type MeQueryResult = ApolloReactCommon.QueryResult<MeQuery, MeQueryVariables>;
|
||||
export const CreateProjectMemberDocument = gql`
|
||||
mutation createProjectMember($projectID: UUID!, $userID: UUID!) {
|
||||
createProjectMember(input: {projectID: $projectID, userID: $userID}) {
|
||||
ok
|
||||
member {
|
||||
id
|
||||
fullName
|
||||
profileIcon {
|
||||
url
|
||||
initials
|
||||
bgColor
|
||||
}
|
||||
username
|
||||
role {
|
||||
code
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type CreateProjectMemberMutationFn = ApolloReactCommon.MutationFunction<CreateProjectMemberMutation, CreateProjectMemberMutationVariables>;
|
||||
|
||||
/**
|
||||
* __useCreateProjectMemberMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useCreateProjectMemberMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useCreateProjectMemberMutation` returns a tuple that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - An object with fields that represent the current status of the mutation's execution
|
||||
*
|
||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||
*
|
||||
* @example
|
||||
* const [createProjectMemberMutation, { data, loading, error }] = useCreateProjectMemberMutation({
|
||||
* variables: {
|
||||
* projectID: // value for 'projectID'
|
||||
* userID: // value for 'userID'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useCreateProjectMemberMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<CreateProjectMemberMutation, CreateProjectMemberMutationVariables>) {
|
||||
return ApolloReactHooks.useMutation<CreateProjectMemberMutation, CreateProjectMemberMutationVariables>(CreateProjectMemberDocument, baseOptions);
|
||||
}
|
||||
export type CreateProjectMemberMutationHookResult = ReturnType<typeof useCreateProjectMemberMutation>;
|
||||
export type CreateProjectMemberMutationResult = ApolloReactCommon.MutationResult<CreateProjectMemberMutation>;
|
||||
export type CreateProjectMemberMutationOptions = ApolloReactCommon.BaseMutationOptions<CreateProjectMemberMutation, CreateProjectMemberMutationVariables>;
|
||||
export const DeleteProjectDocument = gql`
|
||||
mutation deleteProject($projectID: UUID!) {
|
||||
deleteProject(input: {projectID: $projectID}) {
|
||||
@ -3003,6 +2978,54 @@ export function useDeleteProjectMemberMutation(baseOptions?: ApolloReactHooks.Mu
|
||||
export type DeleteProjectMemberMutationHookResult = ReturnType<typeof useDeleteProjectMemberMutation>;
|
||||
export type DeleteProjectMemberMutationResult = ApolloReactCommon.MutationResult<DeleteProjectMemberMutation>;
|
||||
export type DeleteProjectMemberMutationOptions = ApolloReactCommon.BaseMutationOptions<DeleteProjectMemberMutation, DeleteProjectMemberMutationVariables>;
|
||||
export const InviteProjectMemberDocument = gql`
|
||||
mutation inviteProjectMember($projectID: UUID!, $userID: UUID, $email: String) {
|
||||
inviteProjectMember(input: {projectID: $projectID, userID: $userID, email: $email}) {
|
||||
ok
|
||||
member {
|
||||
id
|
||||
fullName
|
||||
profileIcon {
|
||||
url
|
||||
initials
|
||||
bgColor
|
||||
}
|
||||
username
|
||||
role {
|
||||
code
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type InviteProjectMemberMutationFn = ApolloReactCommon.MutationFunction<InviteProjectMemberMutation, InviteProjectMemberMutationVariables>;
|
||||
|
||||
/**
|
||||
* __useInviteProjectMemberMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useInviteProjectMemberMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useInviteProjectMemberMutation` returns a tuple that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - An object with fields that represent the current status of the mutation's execution
|
||||
*
|
||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||
*
|
||||
* @example
|
||||
* const [inviteProjectMemberMutation, { data, loading, error }] = useInviteProjectMemberMutation({
|
||||
* variables: {
|
||||
* projectID: // value for 'projectID'
|
||||
* userID: // value for 'userID'
|
||||
* email: // value for 'email'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useInviteProjectMemberMutation(baseOptions?: ApolloReactHooks.MutationHookOptions<InviteProjectMemberMutation, InviteProjectMemberMutationVariables>) {
|
||||
return ApolloReactHooks.useMutation<InviteProjectMemberMutation, InviteProjectMemberMutationVariables>(InviteProjectMemberDocument, baseOptions);
|
||||
}
|
||||
export type InviteProjectMemberMutationHookResult = ReturnType<typeof useInviteProjectMemberMutation>;
|
||||
export type InviteProjectMemberMutationResult = ApolloReactCommon.MutationResult<InviteProjectMemberMutation>;
|
||||
export type InviteProjectMemberMutationOptions = ApolloReactCommon.BaseMutationOptions<InviteProjectMemberMutation, InviteProjectMemberMutationVariables>;
|
||||
export const UpdateProjectMemberRoleDocument = gql`
|
||||
mutation updateProjectMemberRole($projectID: UUID!, $userID: UUID!, $roleCode: RoleCode!) {
|
||||
updateProjectMemberRole(input: {projectID: $projectID, userID: $userID, roleCode: $roleCode}) {
|
||||
|
@ -1,25 +0,0 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const CREATE_PROJECT_MEMBER_MUTATION = gql`
|
||||
mutation createProjectMember($projectID: UUID!, $userID: UUID!) {
|
||||
createProjectMember(input: { projectID: $projectID, userID: $userID }) {
|
||||
ok
|
||||
member {
|
||||
id
|
||||
fullName
|
||||
profileIcon {
|
||||
url
|
||||
initials
|
||||
bgColor
|
||||
}
|
||||
username
|
||||
role {
|
||||
code
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default CREATE_PROJECT_MEMBER_MUTATION;
|
25
frontend/src/shared/graphql/project/inviteProjectMember.ts
Normal file
25
frontend/src/shared/graphql/project/inviteProjectMember.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import gql from 'graphql-tag';
|
||||
|
||||
export const INVITE_PROJECT_MEMBER_MUTATION = gql`
|
||||
mutation inviteProjectMember($projectID: UUID!, $userID: UUID, $email: String) {
|
||||
inviteProjectMember(input: { projectID: $projectID, userID: $userID, email: $email }) {
|
||||
ok
|
||||
member {
|
||||
id
|
||||
fullName
|
||||
profileIcon {
|
||||
url
|
||||
initials
|
||||
bgColor
|
||||
}
|
||||
username
|
||||
role {
|
||||
code
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export default INVITE_PROJECT_MEMBER_MUTATION;
|
Reference in New Issue
Block a user