feat: redesign project sharing
This commit is contained in:
parent
36f25391b4
commit
737d2b640f
@ -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]});
|
||||
${props =>
|
||||
props.hoverVariant === 'boxShadow' &&
|
||||
css`
|
||||
&:hover {
|
||||
box-shadow: 0 8px 25px -8px rgba(${props => props.theme.colors[props.color]});
|
||||
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;
|
||||
${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();
|
||||
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;
|
1
go.sum
1
go.sum
@ -109,6 +109,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSY
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
|
||||
github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369 h1:XNT/Zf5l++1Pyg08/HV04ppB0gKxAqtZQBRYiYrUuYk=
|
||||
github.com/cznic/mathutil v0.0.0-20180504122225-ca4c9f2c1369/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
@ -16,7 +16,7 @@ UPDATE user_account SET profile_avatar_url = $2 WHERE user_id = $1
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetMemberData :many
|
||||
SELECT username, email, user_id FROM user_account;
|
||||
SELECT username, full_name, email, user_id FROM user_account;
|
||||
|
||||
-- name: UpdateUserAccountInfo :one
|
||||
UPDATE user_account SET bio = $2, full_name = $3, initials = $4, email = $5
|
||||
|
@ -102,11 +102,12 @@ func (q *Queries) GetAllUserAccounts(ctx context.Context) ([]UserAccount, error)
|
||||
}
|
||||
|
||||
const getMemberData = `-- name: GetMemberData :many
|
||||
SELECT username, email, user_id FROM user_account
|
||||
SELECT username, full_name, email, user_id FROM user_account
|
||||
`
|
||||
|
||||
type GetMemberDataRow struct {
|
||||
Username string `json:"username"`
|
||||
FullName string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
UserID uuid.UUID `json:"user_id"`
|
||||
}
|
||||
@ -120,7 +121,12 @@ func (q *Queries) GetMemberData(ctx context.Context) ([]GetMemberDataRow, error)
|
||||
var items []GetMemberDataRow
|
||||
for rows.Next() {
|
||||
var i GetMemberDataRow
|
||||
if err := rows.Scan(&i.Username, &i.Email, &i.UserID); err != nil {
|
||||
if err := rows.Scan(
|
||||
&i.Username,
|
||||
&i.FullName,
|
||||
&i.Email,
|
||||
&i.UserID,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
|
@ -65,11 +65,6 @@ type ComplexityRoot struct {
|
||||
Total func(childComplexity int) int
|
||||
}
|
||||
|
||||
CreateProjectMemberPayload struct {
|
||||
Member func(childComplexity int) int
|
||||
Ok func(childComplexity int) int
|
||||
}
|
||||
|
||||
CreateTeamMemberPayload struct {
|
||||
Team func(childComplexity int) int
|
||||
TeamMember func(childComplexity int) int
|
||||
@ -132,6 +127,11 @@ type ComplexityRoot struct {
|
||||
TaskGroup func(childComplexity int) int
|
||||
}
|
||||
|
||||
InviteProjectMemberPayload struct {
|
||||
Member func(childComplexity int) int
|
||||
Ok func(childComplexity int) int
|
||||
}
|
||||
|
||||
LabelColor struct {
|
||||
ColorHex func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
@ -162,11 +162,10 @@ type ComplexityRoot struct {
|
||||
|
||||
MemberSearchResult struct {
|
||||
Confirmed func(childComplexity int) int
|
||||
FullName func(childComplexity int) int
|
||||
ID func(childComplexity int) int
|
||||
Invited func(childComplexity int) int
|
||||
Joined func(childComplexity int) int
|
||||
Similarity func(childComplexity int) int
|
||||
Username func(childComplexity int) int
|
||||
User func(childComplexity int) int
|
||||
}
|
||||
|
||||
Mutation struct {
|
||||
@ -175,7 +174,6 @@ type ComplexityRoot struct {
|
||||
ClearProfileAvatar func(childComplexity int) int
|
||||
CreateProject func(childComplexity int, input NewProject) int
|
||||
CreateProjectLabel func(childComplexity int, input NewProjectLabel) int
|
||||
CreateProjectMember func(childComplexity int, input CreateProjectMember) int
|
||||
CreateRefreshToken func(childComplexity int, input NewRefreshToken) int
|
||||
CreateTask func(childComplexity int, input NewTask) int
|
||||
CreateTaskChecklist func(childComplexity int, input CreateTaskChecklist) int
|
||||
@ -196,6 +194,7 @@ type ComplexityRoot struct {
|
||||
DeleteTeamMember func(childComplexity int, input DeleteTeamMember) int
|
||||
DeleteUserAccount func(childComplexity int, input DeleteUserAccount) int
|
||||
DuplicateTaskGroup func(childComplexity int, input DuplicateTaskGroup) int
|
||||
InviteProjectMember func(childComplexity int, input InviteProjectMember) int
|
||||
LogoutUser func(childComplexity int, input LogoutUser) int
|
||||
RemoveTaskLabel func(childComplexity int, input *RemoveTaskLabelInput) int
|
||||
SetTaskChecklistItemComplete func(childComplexity int, input SetTaskChecklistItemComplete) int
|
||||
@ -455,7 +454,7 @@ type MutationResolver interface {
|
||||
UpdateProjectLabel(ctx context.Context, input UpdateProjectLabel) (*db.ProjectLabel, error)
|
||||
UpdateProjectLabelName(ctx context.Context, input UpdateProjectLabelName) (*db.ProjectLabel, error)
|
||||
UpdateProjectLabelColor(ctx context.Context, input UpdateProjectLabelColor) (*db.ProjectLabel, error)
|
||||
CreateProjectMember(ctx context.Context, input CreateProjectMember) (*CreateProjectMemberPayload, error)
|
||||
InviteProjectMember(ctx context.Context, input InviteProjectMember) (*InviteProjectMemberPayload, error)
|
||||
DeleteProjectMember(ctx context.Context, input DeleteProjectMember) (*DeleteProjectMemberPayload, error)
|
||||
UpdateProjectMemberRole(ctx context.Context, input UpdateProjectMemberRole) (*UpdateProjectMemberRolePayload, error)
|
||||
CreateTask(ctx context.Context, input NewTask) (*db.Task, error)
|
||||
@ -620,20 +619,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.ChecklistBadge.Total(childComplexity), true
|
||||
|
||||
case "CreateProjectMemberPayload.member":
|
||||
if e.complexity.CreateProjectMemberPayload.Member == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.CreateProjectMemberPayload.Member(childComplexity), true
|
||||
|
||||
case "CreateProjectMemberPayload.ok":
|
||||
if e.complexity.CreateProjectMemberPayload.Ok == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.CreateProjectMemberPayload.Ok(childComplexity), true
|
||||
|
||||
case "CreateTeamMemberPayload.team":
|
||||
if e.complexity.CreateTeamMemberPayload.Team == nil {
|
||||
break
|
||||
@ -816,6 +801,20 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.DuplicateTaskGroupPayload.TaskGroup(childComplexity), true
|
||||
|
||||
case "InviteProjectMemberPayload.member":
|
||||
if e.complexity.InviteProjectMemberPayload.Member == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.InviteProjectMemberPayload.Member(childComplexity), true
|
||||
|
||||
case "InviteProjectMemberPayload.ok":
|
||||
if e.complexity.InviteProjectMemberPayload.Ok == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.InviteProjectMemberPayload.Ok(childComplexity), true
|
||||
|
||||
case "LabelColor.colorHex":
|
||||
if e.complexity.LabelColor.ColorHex == nil {
|
||||
break
|
||||
@ -935,19 +934,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.MemberSearchResult.Confirmed(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.fullName":
|
||||
if e.complexity.MemberSearchResult.FullName == nil {
|
||||
case "MemberSearchResult.invited":
|
||||
if e.complexity.MemberSearchResult.Invited == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.FullName(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.id":
|
||||
if e.complexity.MemberSearchResult.ID == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.ID(childComplexity), true
|
||||
return e.complexity.MemberSearchResult.Invited(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.joined":
|
||||
if e.complexity.MemberSearchResult.Joined == nil {
|
||||
@ -963,12 +955,12 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.MemberSearchResult.Similarity(childComplexity), true
|
||||
|
||||
case "MemberSearchResult.username":
|
||||
if e.complexity.MemberSearchResult.Username == nil {
|
||||
case "MemberSearchResult.user":
|
||||
if e.complexity.MemberSearchResult.User == nil {
|
||||
break
|
||||
}
|
||||
|
||||
return e.complexity.MemberSearchResult.Username(childComplexity), true
|
||||
return e.complexity.MemberSearchResult.User(childComplexity), true
|
||||
|
||||
case "Mutation.addTaskLabel":
|
||||
if e.complexity.Mutation.AddTaskLabel == nil {
|
||||
@ -1025,18 +1017,6 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Mutation.CreateProjectLabel(childComplexity, args["input"].(NewProjectLabel)), true
|
||||
|
||||
case "Mutation.createProjectMember":
|
||||
if e.complexity.Mutation.CreateProjectMember == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_createProjectMember_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.CreateProjectMember(childComplexity, args["input"].(CreateProjectMember)), true
|
||||
|
||||
case "Mutation.createRefreshToken":
|
||||
if e.complexity.Mutation.CreateRefreshToken == nil {
|
||||
break
|
||||
@ -1277,6 +1257,18 @@ func (e *executableSchema) Complexity(typeName, field string, childComplexity in
|
||||
|
||||
return e.complexity.Mutation.DuplicateTaskGroup(childComplexity, args["input"].(DuplicateTaskGroup)), true
|
||||
|
||||
case "Mutation.inviteProjectMember":
|
||||
if e.complexity.Mutation.InviteProjectMember == nil {
|
||||
break
|
||||
}
|
||||
|
||||
args, err := ec.field_Mutation_inviteProjectMember_args(context.TODO(), rawArgs)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return e.complexity.Mutation.InviteProjectMember(childComplexity, args["input"].(InviteProjectMember)), true
|
||||
|
||||
case "Mutation.logoutUser":
|
||||
if e.complexity.Mutation.LogoutUser == nil {
|
||||
break
|
||||
@ -2877,20 +2869,22 @@ input UpdateProjectLabelColor {
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
createProjectMember(input: CreateProjectMember!):
|
||||
CreateProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
# TODO: rename to inviteProjectMember
|
||||
inviteProjectMember(input: InviteProjectMember!):
|
||||
InviteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
deleteProjectMember(input: DeleteProjectMember!):
|
||||
DeleteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!):
|
||||
UpdateProjectMemberRolePayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
}
|
||||
|
||||
input CreateProjectMember {
|
||||
input InviteProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
userID: UUID
|
||||
email: String
|
||||
}
|
||||
|
||||
type CreateProjectMemberPayload {
|
||||
type InviteProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
@ -3283,11 +3277,10 @@ input MemberSearchFilter {
|
||||
}
|
||||
|
||||
type MemberSearchResult {
|
||||
id: UUID!
|
||||
similarity: Int!
|
||||
username: String!
|
||||
fullName: String!
|
||||
user: UserAccount!
|
||||
confirmed: Boolean!
|
||||
invited: Boolean!
|
||||
joined: Boolean!
|
||||
}
|
||||
|
||||
@ -3428,20 +3421,6 @@ func (ec *executionContext) field_Mutation_createProjectLabel_args(ctx context.C
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_createProjectMember_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 CreateProjectMember
|
||||
if tmp, ok := rawArgs["input"]; ok {
|
||||
arg0, err = ec.unmarshalNCreateProjectMember2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐCreateProjectMember(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args["input"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_createProject_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
@ -3736,6 +3715,20 @@ func (ec *executionContext) field_Mutation_duplicateTaskGroup_args(ctx context.C
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_inviteProjectMember_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
var arg0 InviteProjectMember
|
||||
if tmp, ok := rawArgs["input"]; ok {
|
||||
arg0, err = ec.unmarshalNInviteProjectMember2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMember(ctx, tmp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
args["input"] = arg0
|
||||
return args, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) field_Mutation_logoutUser_args(ctx context.Context, rawArgs map[string]interface{}) (map[string]interface{}, error) {
|
||||
var err error
|
||||
args := map[string]interface{}{}
|
||||
@ -4302,74 +4295,6 @@ func (ec *executionContext) _ChecklistBadge_total(ctx context.Context, field gra
|
||||
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _CreateProjectMemberPayload_ok(ctx context.Context, field graphql.CollectedField, obj *CreateProjectMemberPayload) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "CreateProjectMemberPayload",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Ok, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _CreateProjectMemberPayload_member(ctx context.Context, field graphql.CollectedField, obj *CreateProjectMemberPayload) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "CreateProjectMemberPayload",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Member, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*Member)
|
||||
fc.Result = res
|
||||
return ec.marshalNMember2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMember(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _CreateTeamMemberPayload_team(ctx context.Context, field graphql.CollectedField, obj *CreateTeamMemberPayload) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -5254,6 +5179,74 @@ func (ec *executionContext) _DuplicateTaskGroupPayload_taskGroup(ctx context.Con
|
||||
return ec.marshalNTaskGroup2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐTaskGroup(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _InviteProjectMemberPayload_ok(ctx context.Context, field graphql.CollectedField, obj *InviteProjectMemberPayload) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "InviteProjectMemberPayload",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Ok, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _InviteProjectMemberPayload_member(ctx context.Context, field graphql.CollectedField, obj *InviteProjectMemberPayload) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "InviteProjectMemberPayload",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Member, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*Member)
|
||||
fc.Result = res
|
||||
return ec.marshalNMember2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐMember(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _LabelColor_id(ctx context.Context, field graphql.CollectedField, obj *db.LabelColor) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -5798,40 +5791,6 @@ func (ec *executionContext) _MemberList_projects(ctx context.Context, field grap
|
||||
return ec.marshalNProject2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐProjectᚄ(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_id(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.ID, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(uuid.UUID)
|
||||
fc.Result = res
|
||||
return ec.marshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_similarity(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -5866,7 +5825,7 @@ func (ec *executionContext) _MemberSearchResult_similarity(ctx context.Context,
|
||||
return ec.marshalNInt2int(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_username(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _MemberSearchResult_user(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
@ -5883,7 +5842,7 @@ func (ec *executionContext) _MemberSearchResult_username(ctx context.Context, fi
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Username, nil
|
||||
return obj.User, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@ -5895,43 +5854,9 @@ func (ec *executionContext) _MemberSearchResult_username(ctx context.Context, fi
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
res := resTmp.(*db.UserAccount)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_fullName(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.FullName, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(string)
|
||||
fc.Result = res
|
||||
return ec.marshalNString2string(ctx, field.Selections, res)
|
||||
return ec.marshalNUserAccount2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐUserAccount(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_confirmed(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
@ -5968,6 +5893,40 @@ func (ec *executionContext) _MemberSearchResult_confirmed(ctx context.Context, f
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_invited(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
ret = graphql.Null
|
||||
}
|
||||
}()
|
||||
fc := &graphql.FieldContext{
|
||||
Object: "MemberSearchResult",
|
||||
Field: field,
|
||||
Args: nil,
|
||||
IsMethod: false,
|
||||
}
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return obj.Invited, nil
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
}
|
||||
if resTmp == nil {
|
||||
if !graphql.HasFieldError(ctx, fc) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(bool)
|
||||
fc.Result = res
|
||||
return ec.marshalNBoolean2bool(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _MemberSearchResult_joined(ctx context.Context, field graphql.CollectedField, obj *MemberSearchResult) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
@ -6586,7 +6545,7 @@ func (ec *executionContext) _Mutation_updateProjectLabelColor(ctx context.Contex
|
||||
return ec.marshalNProjectLabel2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐProjectLabel(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_createProjectMember(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
func (ec *executionContext) _Mutation_inviteProjectMember(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
ec.Error(ctx, ec.Recover(ctx, r))
|
||||
@ -6602,7 +6561,7 @@ func (ec *executionContext) _Mutation_createProjectMember(ctx context.Context, f
|
||||
|
||||
ctx = graphql.WithFieldContext(ctx, fc)
|
||||
rawArgs := field.ArgumentMap(ec.Variables)
|
||||
args, err := ec.field_Mutation_createProjectMember_args(ctx, rawArgs)
|
||||
args, err := ec.field_Mutation_inviteProjectMember_args(ctx, rawArgs)
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
return graphql.Null
|
||||
@ -6611,7 +6570,7 @@ func (ec *executionContext) _Mutation_createProjectMember(ctx context.Context, f
|
||||
resTmp, err := ec.ResolverMiddleware(ctx, func(rctx context.Context) (interface{}, error) {
|
||||
directive0 := func(rctx context.Context) (interface{}, error) {
|
||||
ctx = rctx // use context from middleware stack in children
|
||||
return ec.resolvers.Mutation().CreateProjectMember(rctx, args["input"].(CreateProjectMember))
|
||||
return ec.resolvers.Mutation().InviteProjectMember(rctx, args["input"].(InviteProjectMember))
|
||||
}
|
||||
directive1 := func(ctx context.Context) (interface{}, error) {
|
||||
roles, err := ec.unmarshalNRoleLevel2ᚕgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐRoleLevelᚄ(ctx, []interface{}{"ADMIN"})
|
||||
@ -6639,10 +6598,10 @@ func (ec *executionContext) _Mutation_createProjectMember(ctx context.Context, f
|
||||
if tmp == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if data, ok := tmp.(*CreateProjectMemberPayload); ok {
|
||||
if data, ok := tmp.(*InviteProjectMemberPayload); ok {
|
||||
return data, nil
|
||||
}
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/jordanknott/taskcafe/internal/graph.CreateProjectMemberPayload`, tmp)
|
||||
return nil, fmt.Errorf(`unexpected type %T from directive, should be *github.com/jordanknott/taskcafe/internal/graph.InviteProjectMemberPayload`, tmp)
|
||||
})
|
||||
if err != nil {
|
||||
ec.Error(ctx, err)
|
||||
@ -6654,9 +6613,9 @@ func (ec *executionContext) _Mutation_createProjectMember(ctx context.Context, f
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
res := resTmp.(*CreateProjectMemberPayload)
|
||||
res := resTmp.(*InviteProjectMemberPayload)
|
||||
fc.Result = res
|
||||
return ec.marshalNCreateProjectMemberPayload2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐCreateProjectMemberPayload(ctx, field.Selections, res)
|
||||
return ec.marshalNInviteProjectMemberPayload2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMemberPayload(ctx, field.Selections, res)
|
||||
}
|
||||
|
||||
func (ec *executionContext) _Mutation_deleteProjectMember(ctx context.Context, field graphql.CollectedField) (ret graphql.Marshaler) {
|
||||
@ -15030,30 +14989,6 @@ func (ec *executionContext) unmarshalInputAssignTaskInput(ctx context.Context, o
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputCreateProjectMember(ctx context.Context, obj interface{}) (CreateProjectMember, error) {
|
||||
var it CreateProjectMember
|
||||
var asMap = obj.(map[string]interface{})
|
||||
|
||||
for k, v := range asMap {
|
||||
switch k {
|
||||
case "projectID":
|
||||
var err error
|
||||
it.ProjectID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "userID":
|
||||
var err error
|
||||
it.UserID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputCreateTaskChecklist(ctx context.Context, obj interface{}) (CreateTaskChecklist, error) {
|
||||
var it CreateTaskChecklist
|
||||
var asMap = obj.(map[string]interface{})
|
||||
@ -15468,6 +15403,36 @@ func (ec *executionContext) unmarshalInputFindUser(ctx context.Context, obj inte
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputInviteProjectMember(ctx context.Context, obj interface{}) (InviteProjectMember, error) {
|
||||
var it InviteProjectMember
|
||||
var asMap = obj.(map[string]interface{})
|
||||
|
||||
for k, v := range asMap {
|
||||
switch k {
|
||||
case "projectID":
|
||||
var err error
|
||||
it.ProjectID, err = ec.unmarshalNUUID2githubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "userID":
|
||||
var err error
|
||||
it.UserID, err = ec.unmarshalOUUID2ᚖgithubᚗcomᚋgoogleᚋuuidᚐUUID(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
case "email":
|
||||
var err error
|
||||
it.Email, err = ec.unmarshalOString2ᚖstring(ctx, v)
|
||||
if err != nil {
|
||||
return it, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return it, nil
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalInputLogoutUser(ctx context.Context, obj interface{}) (LogoutUser, error) {
|
||||
var it LogoutUser
|
||||
var asMap = obj.(map[string]interface{})
|
||||
@ -16438,38 +16403,6 @@ func (ec *executionContext) _ChecklistBadge(ctx context.Context, sel ast.Selecti
|
||||
return out
|
||||
}
|
||||
|
||||
var createProjectMemberPayloadImplementors = []string{"CreateProjectMemberPayload"}
|
||||
|
||||
func (ec *executionContext) _CreateProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, obj *CreateProjectMemberPayload) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, createProjectMemberPayloadImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("CreateProjectMemberPayload")
|
||||
case "ok":
|
||||
out.Values[i] = ec._CreateProjectMemberPayload_ok(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "member":
|
||||
out.Values[i] = ec._CreateProjectMemberPayload_member(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var createTeamMemberPayloadImplementors = []string{"CreateTeamMemberPayload"}
|
||||
|
||||
func (ec *executionContext) _CreateTeamMemberPayload(ctx context.Context, sel ast.SelectionSet, obj *CreateTeamMemberPayload) graphql.Marshaler {
|
||||
@ -16864,6 +16797,38 @@ func (ec *executionContext) _DuplicateTaskGroupPayload(ctx context.Context, sel
|
||||
return out
|
||||
}
|
||||
|
||||
var inviteProjectMemberPayloadImplementors = []string{"InviteProjectMemberPayload"}
|
||||
|
||||
func (ec *executionContext) _InviteProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, obj *InviteProjectMemberPayload) graphql.Marshaler {
|
||||
fields := graphql.CollectFields(ec.OperationContext, sel, inviteProjectMemberPayloadImplementors)
|
||||
|
||||
out := graphql.NewFieldSet(fields)
|
||||
var invalids uint32
|
||||
for i, field := range fields {
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("InviteProjectMemberPayload")
|
||||
case "ok":
|
||||
out.Values[i] = ec._InviteProjectMemberPayload_ok(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "member":
|
||||
out.Values[i] = ec._InviteProjectMemberPayload_member(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
default:
|
||||
panic("unknown field " + strconv.Quote(field.Name))
|
||||
}
|
||||
}
|
||||
out.Dispatch()
|
||||
if invalids > 0 {
|
||||
return graphql.Null
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
var labelColorImplementors = []string{"LabelColor"}
|
||||
|
||||
func (ec *executionContext) _LabelColor(ctx context.Context, sel ast.SelectionSet, obj *db.LabelColor) graphql.Marshaler {
|
||||
@ -17052,23 +17017,13 @@ func (ec *executionContext) _MemberSearchResult(ctx context.Context, sel ast.Sel
|
||||
switch field.Name {
|
||||
case "__typename":
|
||||
out.Values[i] = graphql.MarshalString("MemberSearchResult")
|
||||
case "id":
|
||||
out.Values[i] = ec._MemberSearchResult_id(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "similarity":
|
||||
out.Values[i] = ec._MemberSearchResult_similarity(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "username":
|
||||
out.Values[i] = ec._MemberSearchResult_username(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "fullName":
|
||||
out.Values[i] = ec._MemberSearchResult_fullName(ctx, field, obj)
|
||||
case "user":
|
||||
out.Values[i] = ec._MemberSearchResult_user(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
@ -17077,6 +17032,11 @@ func (ec *executionContext) _MemberSearchResult(ctx context.Context, sel ast.Sel
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "invited":
|
||||
out.Values[i] = ec._MemberSearchResult_invited(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "joined":
|
||||
out.Values[i] = ec._MemberSearchResult_joined(ctx, field, obj)
|
||||
if out.Values[i] == graphql.Null {
|
||||
@ -17148,8 +17108,8 @@ func (ec *executionContext) _Mutation(ctx context.Context, sel ast.SelectionSet)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
case "createProjectMember":
|
||||
out.Values[i] = ec._Mutation_createProjectMember(ctx, field)
|
||||
case "inviteProjectMember":
|
||||
out.Values[i] = ec._Mutation_inviteProjectMember(ctx, field)
|
||||
if out.Values[i] == graphql.Null {
|
||||
invalids++
|
||||
}
|
||||
@ -19437,24 +19397,6 @@ func (ec *executionContext) marshalNBoolean2bool(ctx context.Context, sel ast.Se
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNCreateProjectMember2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐCreateProjectMember(ctx context.Context, v interface{}) (CreateProjectMember, error) {
|
||||
return ec.unmarshalInputCreateProjectMember(ctx, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNCreateProjectMemberPayload2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐCreateProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, v CreateProjectMemberPayload) graphql.Marshaler {
|
||||
return ec._CreateProjectMemberPayload(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNCreateProjectMemberPayload2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐCreateProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, v *CreateProjectMemberPayload) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._CreateProjectMemberPayload(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNCreateTaskChecklist2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐCreateTaskChecklist(ctx context.Context, v interface{}) (CreateTaskChecklist, error) {
|
||||
return ec.unmarshalInputCreateTaskChecklist(ctx, v)
|
||||
}
|
||||
@ -19750,6 +19692,24 @@ func (ec *executionContext) marshalNInt2int(ctx context.Context, sel ast.Selecti
|
||||
return res
|
||||
}
|
||||
|
||||
func (ec *executionContext) unmarshalNInviteProjectMember2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMember(ctx context.Context, v interface{}) (InviteProjectMember, error) {
|
||||
return ec.unmarshalInputInviteProjectMember(ctx, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNInviteProjectMemberPayload2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, v InviteProjectMemberPayload) graphql.Marshaler {
|
||||
return ec._InviteProjectMemberPayload(ctx, sel, &v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNInviteProjectMemberPayload2ᚖgithubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋgraphᚐInviteProjectMemberPayload(ctx context.Context, sel ast.SelectionSet, v *InviteProjectMemberPayload) graphql.Marshaler {
|
||||
if v == nil {
|
||||
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
|
||||
ec.Errorf(ctx, "must not be null")
|
||||
}
|
||||
return graphql.Null
|
||||
}
|
||||
return ec._InviteProjectMemberPayload(ctx, sel, v)
|
||||
}
|
||||
|
||||
func (ec *executionContext) marshalNLabelColor2githubᚗcomᚋjordanknottᚋtaskcafeᚋinternalᚋdbᚐLabelColor(ctx context.Context, sel ast.SelectionSet, v db.LabelColor) graphql.Marshaler {
|
||||
return ec._LabelColor(ctx, sel, &v)
|
||||
}
|
||||
|
@ -27,16 +27,6 @@ type ChecklistBadge struct {
|
||||
Total int `json:"total"`
|
||||
}
|
||||
|
||||
type CreateProjectMember struct {
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
|
||||
type CreateProjectMemberPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Member *Member `json:"member"`
|
||||
}
|
||||
|
||||
type CreateTaskChecklist struct {
|
||||
TaskID uuid.UUID `json:"taskID"`
|
||||
Name string `json:"name"`
|
||||
@ -187,6 +177,17 @@ type FindUser struct {
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
|
||||
type InviteProjectMember struct {
|
||||
ProjectID uuid.UUID `json:"projectID"`
|
||||
UserID *uuid.UUID `json:"userID"`
|
||||
Email *string `json:"email"`
|
||||
}
|
||||
|
||||
type InviteProjectMemberPayload struct {
|
||||
Ok bool `json:"ok"`
|
||||
Member *Member `json:"member"`
|
||||
}
|
||||
|
||||
type LogoutUser struct {
|
||||
UserID uuid.UUID `json:"userID"`
|
||||
}
|
||||
@ -218,11 +219,10 @@ type MemberSearchFilter struct {
|
||||
}
|
||||
|
||||
type MemberSearchResult struct {
|
||||
ID uuid.UUID `json:"id"`
|
||||
Similarity int `json:"similarity"`
|
||||
Username string `json:"username"`
|
||||
FullName string `json:"fullName"`
|
||||
User *db.UserAccount `json:"user"`
|
||||
Confirmed bool `json:"confirmed"`
|
||||
Invited bool `json:"invited"`
|
||||
Joined bool `json:"joined"`
|
||||
}
|
||||
|
||||
|
@ -338,20 +338,22 @@ input UpdateProjectLabelColor {
|
||||
}
|
||||
|
||||
extend type Mutation {
|
||||
createProjectMember(input: CreateProjectMember!):
|
||||
CreateProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
# TODO: rename to inviteProjectMember
|
||||
inviteProjectMember(input: InviteProjectMember!):
|
||||
InviteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
deleteProjectMember(input: DeleteProjectMember!):
|
||||
DeleteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!):
|
||||
UpdateProjectMemberRolePayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
}
|
||||
|
||||
input CreateProjectMember {
|
||||
input InviteProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
userID: UUID
|
||||
email: String
|
||||
}
|
||||
|
||||
type CreateProjectMemberPayload {
|
||||
type InviteProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
@ -744,11 +746,10 @@ input MemberSearchFilter {
|
||||
}
|
||||
|
||||
type MemberSearchResult {
|
||||
id: UUID!
|
||||
similarity: Int!
|
||||
username: String!
|
||||
fullName: String!
|
||||
user: UserAccount!
|
||||
confirmed: Boolean!
|
||||
invited: Boolean!
|
||||
joined: Boolean!
|
||||
}
|
||||
|
||||
|
@ -124,15 +124,32 @@ func (r *mutationResolver) UpdateProjectLabelColor(ctx context.Context, input Up
|
||||
return &label, err
|
||||
}
|
||||
|
||||
func (r *mutationResolver) CreateProjectMember(ctx context.Context, input CreateProjectMember) (*CreateProjectMemberPayload, error) {
|
||||
addedAt := time.Now().UTC()
|
||||
_, err := r.Repository.CreateProjectMember(ctx, db.CreateProjectMemberParams{ProjectID: input.ProjectID, UserID: input.UserID, AddedAt: addedAt, RoleCode: "member"})
|
||||
if err != nil {
|
||||
return &CreateProjectMemberPayload{Ok: false}, err
|
||||
func (r *mutationResolver) InviteProjectMember(ctx context.Context, input InviteProjectMember) (*InviteProjectMemberPayload, error) {
|
||||
if input.Email != nil && input.UserID != nil {
|
||||
return &InviteProjectMemberPayload{Ok: false}, &gqlerror.Error{
|
||||
Message: "Both email and userID can not be used to invite a project member",
|
||||
Extensions: map[string]interface{}{
|
||||
"code": "403",
|
||||
},
|
||||
}
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, input.UserID)
|
||||
} else if input.Email == nil && input.UserID == nil {
|
||||
return &InviteProjectMemberPayload{Ok: false}, &gqlerror.Error{
|
||||
Message: "Either email or userID must be set to invite a project member",
|
||||
Extensions: map[string]interface{}{
|
||||
"code": "403",
|
||||
},
|
||||
}
|
||||
}
|
||||
if input.UserID != nil {
|
||||
addedAt := time.Now().UTC()
|
||||
_, err := r.Repository.CreateProjectMember(ctx, db.CreateProjectMemberParams{ProjectID: input.ProjectID, UserID: *input.UserID, AddedAt: addedAt, RoleCode: "member"})
|
||||
if err != nil {
|
||||
return &CreateProjectMemberPayload{Ok: false}, err
|
||||
return &InviteProjectMemberPayload{Ok: false}, err
|
||||
}
|
||||
user, err := r.Repository.GetUserAccountByID(ctx, *input.UserID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return &InviteProjectMemberPayload{Ok: false}, err
|
||||
|
||||
}
|
||||
var url *string
|
||||
if user.ProfileAvatarUrl.Valid {
|
||||
@ -140,17 +157,20 @@ func (r *mutationResolver) CreateProjectMember(ctx context.Context, input Create
|
||||
}
|
||||
profileIcon := &ProfileIcon{url, &user.Initials, &user.ProfileBgColor}
|
||||
|
||||
role, err := r.Repository.GetRoleForProjectMemberByUserID(ctx, db.GetRoleForProjectMemberByUserIDParams{UserID: input.UserID, ProjectID: input.ProjectID})
|
||||
role, err := r.Repository.GetRoleForProjectMemberByUserID(ctx, db.GetRoleForProjectMemberByUserIDParams{UserID: *input.UserID, ProjectID: input.ProjectID})
|
||||
if err != nil {
|
||||
return &CreateProjectMemberPayload{Ok: false}, err
|
||||
return &InviteProjectMemberPayload{Ok: false}, err
|
||||
}
|
||||
return &CreateProjectMemberPayload{Ok: true, Member: &Member{
|
||||
ID: input.UserID,
|
||||
return &InviteProjectMemberPayload{Ok: true, Member: &Member{
|
||||
ID: *input.UserID,
|
||||
FullName: user.FullName,
|
||||
Username: user.Username,
|
||||
ProfileIcon: profileIcon,
|
||||
Role: &db.Role{Code: role.Code, Name: role.Name},
|
||||
}}, nil
|
||||
}
|
||||
// invite user
|
||||
return &InviteProjectMemberPayload{Ok: false}, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (r *mutationResolver) DeleteProjectMember(ctx context.Context, input DeleteProjectMember) (*DeleteProjectMemberPayload, error) {
|
||||
@ -1222,7 +1242,7 @@ func (r *queryResolver) SearchMembers(ctx context.Context, input MemberSearchFil
|
||||
}
|
||||
return []MemberSearchResult{}, err
|
||||
}
|
||||
results = append(results, MemberSearchResult{FullName: user.FullName, Username: user.Username, Joined: false, Confirmed: false, Similarity: rank.Distance, ID: user.UserID})
|
||||
results = append(results, MemberSearchResult{User: &user, Joined: false, Confirmed: false, Similarity: rank.Distance})
|
||||
memberList[masterList[rank.Target]] = true
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,20 @@
|
||||
extend type Mutation {
|
||||
createProjectMember(input: CreateProjectMember!):
|
||||
CreateProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
# TODO: rename to inviteProjectMember
|
||||
inviteProjectMember(input: InviteProjectMember!):
|
||||
InviteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
deleteProjectMember(input: DeleteProjectMember!):
|
||||
DeleteProjectMemberPayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
updateProjectMemberRole(input: UpdateProjectMemberRole!):
|
||||
UpdateProjectMemberRolePayload! @hasRole(roles: [ADMIN], level: PROJECT, type: PROJECT)
|
||||
}
|
||||
|
||||
input CreateProjectMember {
|
||||
input InviteProjectMember {
|
||||
projectID: UUID!
|
||||
userID: UUID!
|
||||
userID: UUID
|
||||
email: String
|
||||
}
|
||||
|
||||
type CreateProjectMemberPayload {
|
||||
type InviteProjectMemberPayload {
|
||||
ok: Boolean!
|
||||
member: Member!
|
||||
}
|
||||
|
@ -25,11 +25,10 @@ input MemberSearchFilter {
|
||||
}
|
||||
|
||||
type MemberSearchResult {
|
||||
id: UUID!
|
||||
similarity: Int!
|
||||
username: String!
|
||||
fullName: String!
|
||||
user: UserAccount!
|
||||
confirmed: Boolean!
|
||||
invited: Boolean!
|
||||
joined: Boolean!
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user