feat: rename comment thread into activity (#939)
* feat: rename commentThread into activity server * feat: rename commentThread into activity front * feat: migration only create tables feat: migration only create tables * Update activities * fix: rebase partial fix * fix: all rebase problems and drop activity target alter * fix: lint * Update migration * Update migration * Fix conflicts * Fix conflicts --------- Co-authored-by: Charles Bochet <charles@twenty.com>
This commit is contained in:
@ -2,7 +2,7 @@ import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
|
||||
import { CommentThreadActionBar } from '../../right-drawer/components/CommentThreadActionBar';
|
||||
import { ActivityActionBar } from '../../right-drawer/components/ActivityActionBar';
|
||||
import { Comment } from '../Comment';
|
||||
|
||||
import { mockComment, mockCommentWithLongValues } from './mock-comment';
|
||||
@ -15,7 +15,7 @@ const meta: Meta<typeof Comment> = {
|
||||
actionBar: {
|
||||
type: 'boolean',
|
||||
mapping: {
|
||||
true: <CommentThreadActionBar commentThreadId="test-id" />,
|
||||
true: <ActivityActionBar activityId="test-id" />,
|
||||
false: undefined,
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
import { CommentThreadActionBar } from '@/activities/right-drawer/components/CommentThreadActionBar';
|
||||
import { ActivityActionBar } from '@/activities/right-drawer/components/ActivityActionBar';
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
import { avatarUrl } from '~/testing/mock-data/users';
|
||||
|
||||
@ -17,7 +17,7 @@ const meta: Meta<typeof CommentHeader> = {
|
||||
actionBar: {
|
||||
type: 'boolean',
|
||||
mapping: {
|
||||
true: <CommentThreadActionBar commentThreadId="test-id" />,
|
||||
true: <ActivityActionBar activityId="test-id" />,
|
||||
false: undefined,
|
||||
},
|
||||
},
|
||||
|
||||
@ -6,24 +6,21 @@ import styled from '@emotion/styled';
|
||||
import debounce from 'lodash.debounce';
|
||||
|
||||
import { BlockEditor } from '@/ui/editor/components/BlockEditor';
|
||||
import {
|
||||
CommentThread,
|
||||
useUpdateCommentThreadMutation,
|
||||
} from '~/generated/graphql';
|
||||
import { Activity, useUpdateActivityMutation } from '~/generated/graphql';
|
||||
|
||||
import { GET_COMMENT_THREADS_BY_TARGETS } from '../queries/select';
|
||||
import { GET_ACTIVITIES_BY_TARGETS } from '../queries/select';
|
||||
|
||||
const BlockNoteStyledContainer = styled.div`
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
commentThread: Pick<CommentThread, 'id' | 'body'>;
|
||||
onChange?: (commentThreadBody: string) => void;
|
||||
activity: Pick<Activity, 'id' | 'body'>;
|
||||
onChange?: (activityBody: string) => void;
|
||||
};
|
||||
|
||||
export function CommentThreadBodyEditor({ commentThread, onChange }: OwnProps) {
|
||||
const [updateCommentThreadMutation] = useUpdateCommentThreadMutation();
|
||||
export function ActivityBodyEditor({ activity, onChange }: OwnProps) {
|
||||
const [updateActivityMutation] = useUpdateActivityMutation();
|
||||
|
||||
const [body, setBody] = useState<string | null>(null);
|
||||
|
||||
@ -34,26 +31,22 @@ export function CommentThreadBodyEditor({ commentThread, onChange }: OwnProps) {
|
||||
}, [body, onChange]);
|
||||
|
||||
const debounceOnChange = useMemo(() => {
|
||||
function onInternalChange(commentThreadBody: string) {
|
||||
setBody(commentThreadBody);
|
||||
updateCommentThreadMutation({
|
||||
function onInternalChange(activityBody: string) {
|
||||
setBody(activityBody);
|
||||
updateActivityMutation({
|
||||
variables: {
|
||||
id: commentThread.id,
|
||||
body: commentThreadBody,
|
||||
id: activity.id,
|
||||
body: activityBody,
|
||||
},
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
],
|
||||
refetchQueries: [getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? ''],
|
||||
});
|
||||
}
|
||||
|
||||
return debounce(onInternalChange, 200);
|
||||
}, [commentThread, updateCommentThreadMutation, setBody]);
|
||||
}, [activity, updateActivityMutation, setBody]);
|
||||
|
||||
const editor: BlockNoteEditor | null = useBlockNote({
|
||||
initialContent: commentThread.body
|
||||
? JSON.parse(commentThread.body)
|
||||
: undefined,
|
||||
initialContent: activity.body ? JSON.parse(activity.body) : undefined,
|
||||
editorDOMAttributes: { class: 'editor' },
|
||||
onEditorContentChange: (editor) => {
|
||||
debounceOnChange(JSON.stringify(editor.topLevelBlocks) ?? '');
|
||||
@ -6,15 +6,15 @@ import { v4 } from 'uuid';
|
||||
import { currentUserState } from '@/auth/states/currentUserState';
|
||||
import { useIsMobile } from '@/ui/hooks/useIsMobile';
|
||||
import { AutosizeTextInput } from '@/ui/input/components/AutosizeTextInput';
|
||||
import { CommentThread, useCreateCommentMutation } from '~/generated/graphql';
|
||||
import { Activity, useCreateCommentMutation } from '~/generated/graphql';
|
||||
import { isNonEmptyString } from '~/utils/isNonEmptyString';
|
||||
|
||||
import { Comment } from '../comment/Comment';
|
||||
import { GET_COMMENT_THREAD } from '../queries';
|
||||
import { GET_ACTIVITY } from '../queries';
|
||||
import { CommentForDrawer } from '../types/CommentForDrawer';
|
||||
|
||||
type OwnProps = {
|
||||
commentThread: Pick<CommentThread, 'id'> & {
|
||||
activity: Pick<Activity, 'id'> & {
|
||||
comments: Array<CommentForDrawer>;
|
||||
};
|
||||
};
|
||||
@ -52,7 +52,7 @@ const StyledThreadCommentTitle = styled.div`
|
||||
text-transform: uppercase;
|
||||
`;
|
||||
|
||||
export function CommentThreadComments({ commentThread }: OwnProps) {
|
||||
export function ActivityComments({ activity }: OwnProps) {
|
||||
const [createCommentMutation] = useCreateCommentMutation();
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
|
||||
@ -69,21 +69,21 @@ export function CommentThreadComments({ commentThread }: OwnProps) {
|
||||
variables: {
|
||||
commentId: v4(),
|
||||
authorId: currentUser?.id ?? '',
|
||||
commentThreadId: commentThread?.id ?? '',
|
||||
activityId: activity?.id ?? '',
|
||||
commentText: commentText,
|
||||
createdAt: new Date().toISOString(),
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_COMMENT_THREAD) ?? ''],
|
||||
refetchQueries: [getOperationName(GET_ACTIVITY) ?? ''],
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{commentThread?.comments.length > 0 && (
|
||||
{activity?.comments.length > 0 && (
|
||||
<>
|
||||
<StyledThreadItemListContainer>
|
||||
<StyledThreadCommentTitle>Comments</StyledThreadCommentTitle>
|
||||
{commentThread?.comments?.map((comment) => (
|
||||
{activity?.comments?.map((comment) => (
|
||||
<Comment key={comment.id} comment={comment} />
|
||||
))}
|
||||
</StyledThreadItemListContainer>
|
||||
@ -4,17 +4,17 @@ import { Button, ButtonVariant } from '@/ui/button/components/Button';
|
||||
import { ButtonGroup } from '@/ui/button/components/ButtonGroup';
|
||||
import { IconCheckbox, IconNotes, IconTimelineEvent } from '@/ui/icon/index';
|
||||
|
||||
type CommentThreadCreateButtonProps = {
|
||||
type ActivityCreateButtonProps = {
|
||||
onNoteClick?: () => void;
|
||||
onTaskClick?: () => void;
|
||||
onActivityClick?: () => void;
|
||||
};
|
||||
|
||||
export function CommentThreadCreateButton({
|
||||
export function ActivityCreateButton({
|
||||
onNoteClick,
|
||||
onTaskClick,
|
||||
onActivityClick,
|
||||
}: CommentThreadCreateButtonProps) {
|
||||
}: ActivityCreateButtonProps) {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<ButtonGroup variant={ButtonVariant.Secondary}>
|
||||
@ -2,26 +2,26 @@ import React, { useCallback, useState } from 'react';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { CommentThreadBodyEditor } from '@/activities/components/CommentThreadBodyEditor';
|
||||
import { CommentThreadComments } from '@/activities/components/CommentThreadComments';
|
||||
import { CommentThreadRelationPicker } from '@/activities/components/CommentThreadRelationPicker';
|
||||
import { CommentThreadTypeDropdown } from '@/activities/components/CommentThreadTypeDropdown';
|
||||
import { GET_COMMENT_THREADS_BY_TARGETS } from '@/activities/queries';
|
||||
import { ActivityBodyEditor } from '@/activities/components/ActivityBodyEditor';
|
||||
import { ActivityComments } from '@/activities/components/ActivityComments';
|
||||
import { ActivityRelationPicker } from '@/activities/components/ActivityRelationPicker';
|
||||
import { ActivityTypeDropdown } from '@/activities/components/ActivityTypeDropdown';
|
||||
import { GET_ACTIVITIES_BY_TARGETS } from '@/activities/queries';
|
||||
import { PropertyBox } from '@/ui/editable-field/property-box/components/PropertyBox';
|
||||
import { PropertyBoxItem } from '@/ui/editable-field/property-box/components/PropertyBoxItem';
|
||||
import { useIsMobile } from '@/ui/hooks/useIsMobile';
|
||||
import { IconArrowUpRight } from '@/ui/icon/index';
|
||||
import {
|
||||
CommentThread,
|
||||
CommentThreadTarget,
|
||||
useUpdateCommentThreadMutation,
|
||||
Activity,
|
||||
ActivityTarget,
|
||||
useUpdateActivityMutation,
|
||||
} from '~/generated/graphql';
|
||||
import { debounce } from '~/utils/debounce';
|
||||
|
||||
import { CommentThreadActionBar } from '../right-drawer/components/CommentThreadActionBar';
|
||||
import { ActivityActionBar } from '../right-drawer/components/ActivityActionBar';
|
||||
import { CommentForDrawer } from '../types/CommentForDrawer';
|
||||
|
||||
import { CommentThreadTitle } from './CommentThreadTitle';
|
||||
import { ActivityTitle } from './ActivityTitle';
|
||||
|
||||
import '@blocknote/core/style.css';
|
||||
|
||||
@ -65,64 +65,57 @@ const StyledTopActionsContainer = styled.div`
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
commentThread: Pick<
|
||||
CommentThread,
|
||||
'id' | 'title' | 'body' | 'type' | 'completedAt'
|
||||
> & {
|
||||
activity: Pick<Activity, 'id' | 'title' | 'body' | 'type' | 'completedAt'> & {
|
||||
comments?: Array<CommentForDrawer> | null;
|
||||
} & {
|
||||
commentThreadTargets?: Array<
|
||||
Pick<CommentThreadTarget, 'id' | 'commentableId' | 'commentableType'>
|
||||
activityTargets?: Array<
|
||||
Pick<ActivityTarget, 'id' | 'commentableId' | 'commentableType'>
|
||||
> | null;
|
||||
};
|
||||
showComment?: boolean;
|
||||
autoFillTitle?: boolean;
|
||||
};
|
||||
|
||||
export function CommentThreadEditor({
|
||||
commentThread,
|
||||
export function ActivityEditor({
|
||||
activity,
|
||||
showComment = true,
|
||||
autoFillTitle = false,
|
||||
}: OwnProps) {
|
||||
const [hasUserManuallySetTitle, setHasUserManuallySetTitle] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const [title, setTitle] = useState<string | null>(commentThread.title ?? '');
|
||||
const [title, setTitle] = useState<string | null>(activity.title ?? '');
|
||||
const [completedAt, setCompletedAt] = useState<string | null>(
|
||||
commentThread.completedAt ?? '',
|
||||
activity.completedAt ?? '',
|
||||
);
|
||||
|
||||
const [updateCommentThreadMutation] = useUpdateCommentThreadMutation();
|
||||
const [updateActivityMutation] = useUpdateActivityMutation();
|
||||
|
||||
const updateTitle = useCallback(
|
||||
(newTitle: string) => {
|
||||
updateCommentThreadMutation({
|
||||
updateActivityMutation({
|
||||
variables: {
|
||||
id: commentThread.id,
|
||||
id: activity.id,
|
||||
title: newTitle ?? '',
|
||||
},
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
],
|
||||
refetchQueries: [getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? ''],
|
||||
});
|
||||
},
|
||||
[commentThread, updateCommentThreadMutation],
|
||||
[activity, updateActivityMutation],
|
||||
);
|
||||
|
||||
const handleActivityCompletionChange = useCallback(
|
||||
(value: boolean) => {
|
||||
updateCommentThreadMutation({
|
||||
updateActivityMutation({
|
||||
variables: {
|
||||
id: commentThread.id,
|
||||
id: activity.id,
|
||||
completedAt: value ? new Date().toISOString() : null,
|
||||
},
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
],
|
||||
refetchQueries: [getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? ''],
|
||||
});
|
||||
setCompletedAt(value ? new Date().toISOString() : null);
|
||||
},
|
||||
[commentThread, updateCommentThreadMutation],
|
||||
[activity, updateActivityMutation],
|
||||
);
|
||||
|
||||
const debouncedUpdateTitle = debounce(updateTitle, 200);
|
||||
@ -135,7 +128,7 @@ export function CommentThreadEditor({
|
||||
}
|
||||
}
|
||||
|
||||
if (!commentThread) {
|
||||
if (!activity) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
@ -144,13 +137,13 @@ export function CommentThreadEditor({
|
||||
<StyledUpperPartContainer>
|
||||
<StyledTopContainer>
|
||||
<StyledTopActionsContainer>
|
||||
<CommentThreadTypeDropdown commentThread={commentThread} />
|
||||
<CommentThreadActionBar commentThreadId={commentThread?.id ?? ''} />
|
||||
<ActivityTypeDropdown activity={activity} />
|
||||
<ActivityActionBar activityId={activity?.id ?? ''} />
|
||||
</StyledTopActionsContainer>
|
||||
<CommentThreadTitle
|
||||
<ActivityTitle
|
||||
title={title ?? ''}
|
||||
completed={!!completedAt}
|
||||
type={commentThread.type}
|
||||
type={activity.type}
|
||||
onTitleChange={(newTitle) => {
|
||||
setTitle(newTitle);
|
||||
setHasUserManuallySetTitle(true);
|
||||
@ -162,11 +155,10 @@ export function CommentThreadEditor({
|
||||
<PropertyBoxItem
|
||||
icon={<IconArrowUpRight />}
|
||||
value={
|
||||
<CommentThreadRelationPicker
|
||||
commentThread={{
|
||||
id: commentThread.id,
|
||||
commentThreadTargets:
|
||||
commentThread.commentThreadTargets ?? [],
|
||||
<ActivityRelationPicker
|
||||
activity={{
|
||||
id: activity.id,
|
||||
activityTargets: activity.activityTargets ?? [],
|
||||
}}
|
||||
/>
|
||||
}
|
||||
@ -174,16 +166,16 @@ export function CommentThreadEditor({
|
||||
/>
|
||||
</PropertyBox>
|
||||
</StyledTopContainer>
|
||||
<CommentThreadBodyEditor
|
||||
commentThread={commentThread}
|
||||
<ActivityBodyEditor
|
||||
activity={activity}
|
||||
onChange={updateTitleFromBody}
|
||||
/>
|
||||
</StyledUpperPartContainer>
|
||||
{showComment && (
|
||||
<CommentThreadComments
|
||||
commentThread={{
|
||||
id: commentThread.id,
|
||||
comments: commentThread.comments ?? [],
|
||||
<ActivityComments
|
||||
activity={{
|
||||
id: activity.id,
|
||||
comments: activity.comments ?? [],
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
@ -18,19 +18,15 @@ import { useScopedHotkeys } from '@/ui/hotkey/hooks/useScopedHotkeys';
|
||||
import { RecoilScope } from '@/ui/recoil-scope/components/RecoilScope';
|
||||
import { MultipleEntitySelect } from '@/ui/relation-picker/components/MultipleEntitySelect';
|
||||
import { RelationPickerHotkeyScope } from '@/ui/relation-picker/types/RelationPickerHotkeyScope';
|
||||
import {
|
||||
CommentableType,
|
||||
CommentThread,
|
||||
CommentThreadTarget,
|
||||
} from '~/generated/graphql';
|
||||
import { Activity, ActivityTarget, CommentableType } from '~/generated/graphql';
|
||||
|
||||
import { useHandleCheckableCommentThreadTargetChange } from '../hooks/useHandleCheckableCommentThreadTargetChange';
|
||||
import { useHandleCheckableActivityTargetChange } from '../hooks/useHandleCheckableActivityTargetChange';
|
||||
import { flatMapAndSortEntityForSelectArrayOfArrayByName } from '../utils/flatMapAndSortEntityForSelectArrayByName';
|
||||
|
||||
type OwnProps = {
|
||||
commentThread?: Pick<CommentThread, 'id'> & {
|
||||
commentThreadTargets: Array<
|
||||
Pick<CommentThreadTarget, 'id' | 'commentableId' | 'commentableType'>
|
||||
activity?: Pick<Activity, 'id'> & {
|
||||
activityTargets: Array<
|
||||
Pick<ActivityTarget, 'id' | 'commentableId' | 'commentableType'>
|
||||
>;
|
||||
};
|
||||
};
|
||||
@ -75,7 +71,7 @@ const StyledMenuWrapper = styled.div`
|
||||
z-index: ${({ theme }) => theme.lastLayerZIndex};
|
||||
`;
|
||||
|
||||
export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
|
||||
export function ActivityRelationPicker({ activity }: OwnProps) {
|
||||
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
||||
const [searchFilter, setSearchFilter] = useState('');
|
||||
const [selectedEntityIds, setSelectedEntityIds] = useState<
|
||||
@ -88,17 +84,18 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
|
||||
|
||||
const initialPeopleIds = useMemo(
|
||||
() =>
|
||||
commentThread?.commentThreadTargets
|
||||
activity?.activityTargets
|
||||
?.filter((relation) => relation.commentableType === 'Person')
|
||||
.map((relation) => relation.commentableId) ?? [],
|
||||
[commentThread?.commentThreadTargets],
|
||||
[activity?.activityTargets],
|
||||
);
|
||||
|
||||
const initialCompanyIds = useMemo(
|
||||
() =>
|
||||
commentThread?.commentThreadTargets
|
||||
activity?.activityTargets
|
||||
?.filter((relation) => relation.commentableType === 'Company')
|
||||
.map((relation) => relation.commentableId) ?? [],
|
||||
[commentThread?.commentThreadTargets],
|
||||
[activity?.activityTargets],
|
||||
);
|
||||
|
||||
const initialSelectedEntityIds = useMemo(
|
||||
@ -135,8 +132,8 @@ export function CommentThreadRelationPicker({ commentThread }: OwnProps) {
|
||||
companiesForMultiSelect.entitiesToSelect,
|
||||
]);
|
||||
|
||||
const handleCheckItemsChange = useHandleCheckableCommentThreadTargetChange({
|
||||
commentThread,
|
||||
const handleCheckItemsChange = useHandleCheckableActivityTargetChange({
|
||||
activity,
|
||||
});
|
||||
|
||||
const exitEditMode = useCallback(() => {
|
||||
@ -51,7 +51,7 @@ type OwnProps = {
|
||||
onCompletionChange: (value: boolean) => void;
|
||||
};
|
||||
|
||||
export function CommentThreadTitle({
|
||||
export function ActivityTitle({
|
||||
title,
|
||||
completed,
|
||||
type,
|
||||
@ -7,17 +7,17 @@ import {
|
||||
ChipVariant,
|
||||
} from '@/ui/chip/components/Chip';
|
||||
import { IconPhone } from '@/ui/icon';
|
||||
import { CommentThread } from '~/generated/graphql';
|
||||
import { Activity } from '~/generated/graphql';
|
||||
|
||||
type OwnProps = {
|
||||
commentThread: Pick<CommentThread, 'type'>;
|
||||
activity: Pick<Activity, 'type'>;
|
||||
};
|
||||
|
||||
export function CommentThreadTypeDropdown({ commentThread }: OwnProps) {
|
||||
export function ActivityTypeDropdown({ activity }: OwnProps) {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Chip
|
||||
label={commentThread.type}
|
||||
label={activity.type}
|
||||
leftComponent={<IconPhone size={theme.icon.size.md} />}
|
||||
size={ChipSize.Large}
|
||||
accent={ChipAccent.TextSecondary}
|
||||
@ -4,17 +4,17 @@ import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { ComponentDecorator } from '~/testing/decorators/ComponentDecorator';
|
||||
import { graphqlMocks } from '~/testing/graphqlMocks';
|
||||
import { mockedCommentThreads } from '~/testing/mock-data/comment-threads';
|
||||
import { mockedActivities } from '~/testing/mock-data/activities';
|
||||
|
||||
import { CommentThreadRelationPicker } from '../CommentThreadRelationPicker';
|
||||
import { ActivityRelationPicker } from '../ActivityRelationPicker';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
width: 400px;
|
||||
`;
|
||||
|
||||
const meta: Meta<typeof CommentThreadRelationPicker> = {
|
||||
title: 'Modules/Comments/CommentThreadRelationPicker',
|
||||
component: CommentThreadRelationPicker,
|
||||
const meta: Meta<typeof ActivityRelationPicker> = {
|
||||
title: 'Modules/Comments/ActivityRelationPicker',
|
||||
component: ActivityRelationPicker,
|
||||
decorators: [
|
||||
(Story) => (
|
||||
<MemoryRouter>
|
||||
@ -25,13 +25,13 @@ const meta: Meta<typeof CommentThreadRelationPicker> = {
|
||||
),
|
||||
ComponentDecorator,
|
||||
],
|
||||
args: { commentThread: mockedCommentThreads[0] },
|
||||
args: { activity: mockedActivities[0] },
|
||||
parameters: {
|
||||
msw: graphqlMocks,
|
||||
},
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof CommentThreadRelationPicker>;
|
||||
type Story = StoryObj<typeof ActivityRelationPicker>;
|
||||
|
||||
export const Default: Story = {};
|
||||
@ -0,0 +1,84 @@
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { GET_COMPANIES } from '@/companies/queries';
|
||||
import { GET_PEOPLE } from '@/people/queries';
|
||||
import {
|
||||
Activity,
|
||||
ActivityTarget,
|
||||
useAddActivityTargetsOnActivityMutation,
|
||||
useRemoveActivityTargetsOnActivityMutation,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_ACTIVITIES_BY_TARGETS } from '../queries';
|
||||
import { CommentableEntityForSelect } from '../types/CommentableEntityForSelect';
|
||||
|
||||
export function useHandleCheckableActivityTargetChange({
|
||||
activity,
|
||||
}: {
|
||||
activity?: Pick<Activity, 'id'> & {
|
||||
activityTargets: Array<
|
||||
Pick<ActivityTarget, 'id' | 'commentableId' | 'commentableType'>
|
||||
>;
|
||||
};
|
||||
}) {
|
||||
const [addActivityTargetsOnActivity] =
|
||||
useAddActivityTargetsOnActivityMutation({
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
const [removeActivityTargetsOnActivity] =
|
||||
useRemoveActivityTargetsOnActivityMutation({
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
return async function handleCheckItemsChange(
|
||||
entityValues: Record<string, boolean>,
|
||||
entities: CommentableEntityForSelect[],
|
||||
) {
|
||||
if (!activity) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentEntityIds = activity.activityTargets.map(
|
||||
({ commentableId }) => commentableId,
|
||||
);
|
||||
|
||||
const entitiesToAdd = entities.filter(
|
||||
({ id }) => entityValues[id] && !currentEntityIds.includes(id),
|
||||
);
|
||||
|
||||
if (entitiesToAdd.length)
|
||||
await addActivityTargetsOnActivity({
|
||||
variables: {
|
||||
activityId: activity.id,
|
||||
activityTargetInputs: entitiesToAdd.map((entity) => ({
|
||||
id: v4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
commentableType: entity.entityType,
|
||||
commentableId: entity.id,
|
||||
})),
|
||||
},
|
||||
});
|
||||
|
||||
const activityTargetIdsToDelete = activity.activityTargets
|
||||
.filter(({ commentableId }) => !entityValues[commentableId])
|
||||
.map(({ id }) => id);
|
||||
|
||||
if (activityTargetIdsToDelete.length)
|
||||
await removeActivityTargetsOnActivity({
|
||||
variables: {
|
||||
activityId: activity.id,
|
||||
activityTargetIds: activityTargetIdsToDelete,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
@ -1,84 +0,0 @@
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import { v4 } from 'uuid';
|
||||
|
||||
import { GET_COMPANIES } from '@/companies/queries';
|
||||
import { GET_PEOPLE } from '@/people/queries';
|
||||
import {
|
||||
CommentThread,
|
||||
CommentThreadTarget,
|
||||
useAddCommentThreadTargetsOnCommentThreadMutation,
|
||||
useRemoveCommentThreadTargetsOnCommentThreadMutation,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_COMMENT_THREADS_BY_TARGETS } from '../queries';
|
||||
import { CommentableEntityForSelect } from '../types/CommentableEntityForSelect';
|
||||
|
||||
export function useHandleCheckableCommentThreadTargetChange({
|
||||
commentThread,
|
||||
}: {
|
||||
commentThread?: Pick<CommentThread, 'id'> & {
|
||||
commentThreadTargets: Array<
|
||||
Pick<CommentThreadTarget, 'id' | 'commentableId'>
|
||||
>;
|
||||
};
|
||||
}) {
|
||||
const [addCommentThreadTargetsOnCommentThread] =
|
||||
useAddCommentThreadTargetsOnCommentThreadMutation({
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
const [removeCommentThreadTargetsOnCommentThread] =
|
||||
useRemoveCommentThreadTargetsOnCommentThreadMutation({
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
],
|
||||
});
|
||||
|
||||
return async function handleCheckItemsChange(
|
||||
entityValues: Record<string, boolean>,
|
||||
entities: CommentableEntityForSelect[],
|
||||
) {
|
||||
if (!commentThread) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentEntityIds = commentThread.commentThreadTargets.map(
|
||||
({ commentableId }) => commentableId,
|
||||
);
|
||||
|
||||
const entitiesToAdd = entities.filter(
|
||||
({ id }) => entityValues[id] && !currentEntityIds.includes(id),
|
||||
);
|
||||
|
||||
if (entitiesToAdd.length)
|
||||
await addCommentThreadTargetsOnCommentThread({
|
||||
variables: {
|
||||
commentThreadId: commentThread.id,
|
||||
commentThreadTargetInputs: entitiesToAdd.map((entity) => ({
|
||||
id: v4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
commentableType: entity.entityType,
|
||||
commentableId: entity.id,
|
||||
})),
|
||||
},
|
||||
});
|
||||
|
||||
const commentThreadTargetIdsToDelete = commentThread.commentThreadTargets
|
||||
.filter(({ commentableId }) => !entityValues[commentableId])
|
||||
.map(({ id }) => id);
|
||||
|
||||
if (commentThreadTargetIdsToDelete.length)
|
||||
await removeCommentThreadTargetsOnCommentThread({
|
||||
variables: {
|
||||
commentThreadId: commentThread.id,
|
||||
commentThreadTargetIds: commentThreadTargetIdsToDelete,
|
||||
},
|
||||
});
|
||||
};
|
||||
}
|
||||
@ -5,18 +5,16 @@ import { useRightDrawer } from '@/ui/right-drawer/hooks/useRightDrawer';
|
||||
import { RightDrawerHotkeyScope } from '@/ui/right-drawer/types/RightDrawerHotkeyScope';
|
||||
import { RightDrawerPages } from '@/ui/right-drawer/types/RightDrawerPages';
|
||||
|
||||
import { viewableCommentThreadIdState } from '../states/viewableCommentThreadIdState';
|
||||
import { viewableActivityIdState } from '../states/viewableActivityIdState';
|
||||
|
||||
export function useOpenCommentThreadRightDrawer() {
|
||||
export function useOpenActivityRightDrawer() {
|
||||
const { openRightDrawer } = useRightDrawer();
|
||||
const [, setViewableCommentThreadId] = useRecoilState(
|
||||
viewableCommentThreadIdState,
|
||||
);
|
||||
const [, setViewableActivityId] = useRecoilState(viewableActivityIdState);
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
return function openCommentThreadRightDrawer(commentThreadId: string) {
|
||||
return function openActivityRightDrawer(activityId: string) {
|
||||
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
|
||||
setViewableCommentThreadId(commentThreadId);
|
||||
openRightDrawer(RightDrawerPages.EditCommentThread);
|
||||
setViewableActivityId(activityId);
|
||||
openRightDrawer(RightDrawerPages.EditActivity);
|
||||
};
|
||||
}
|
||||
@ -9,40 +9,35 @@ import { useSetHotkeyScope } from '@/ui/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useRightDrawer } from '@/ui/right-drawer/hooks/useRightDrawer';
|
||||
import { RightDrawerHotkeyScope } from '@/ui/right-drawer/types/RightDrawerHotkeyScope';
|
||||
import { RightDrawerPages } from '@/ui/right-drawer/types/RightDrawerPages';
|
||||
import {
|
||||
ActivityType,
|
||||
useCreateCommentThreadMutation,
|
||||
} from '~/generated/graphql';
|
||||
import { ActivityType, useCreateActivityMutation } from '~/generated/graphql';
|
||||
|
||||
import { GET_COMMENT_THREAD, GET_COMMENT_THREADS_BY_TARGETS } from '../queries';
|
||||
import { GET_ACTIVITIES_BY_TARGETS, GET_ACTIVITY } from '../queries';
|
||||
import { commentableEntityArrayState } from '../states/commentableEntityArrayState';
|
||||
import { viewableCommentThreadIdState } from '../states/viewableCommentThreadIdState';
|
||||
import { viewableActivityIdState } from '../states/viewableActivityIdState';
|
||||
import { CommentableEntity } from '../types/CommentableEntity';
|
||||
|
||||
export function useOpenCreateCommentThreadDrawer() {
|
||||
export function useOpenCreateActivityDrawer() {
|
||||
const { openRightDrawer } = useRightDrawer();
|
||||
const [createCommentThreadMutation] = useCreateCommentThreadMutation();
|
||||
const [createActivityMutation] = useCreateActivityMutation();
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
const [, setCommentableEntityArray] = useRecoilState(
|
||||
commentableEntityArrayState,
|
||||
);
|
||||
const [, setViewableCommentThreadId] = useRecoilState(
|
||||
viewableCommentThreadIdState,
|
||||
);
|
||||
const [, setViewableActivityId] = useRecoilState(viewableActivityIdState);
|
||||
|
||||
return function openCreateCommentThreadDrawer(
|
||||
return function openCreateActivityDrawer(
|
||||
entity: CommentableEntity,
|
||||
type: ActivityType,
|
||||
) {
|
||||
createCommentThreadMutation({
|
||||
createActivityMutation({
|
||||
variables: {
|
||||
authorId: currentUser?.id ?? '',
|
||||
commentThreadId: v4(),
|
||||
activityId: v4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
type: type,
|
||||
commentThreadTargetArray: [
|
||||
activityTargetArray: [
|
||||
{
|
||||
commentableId: entity.id,
|
||||
commentableType: entity.type,
|
||||
@ -54,14 +49,14 @@ export function useOpenCreateCommentThreadDrawer() {
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
getOperationName(GET_COMMENT_THREAD) ?? '',
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
getOperationName(GET_ACTIVITY) ?? '',
|
||||
getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? '',
|
||||
],
|
||||
onCompleted(data) {
|
||||
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
|
||||
setViewableCommentThreadId(data.createOneCommentThread.id);
|
||||
setViewableActivityId(data.createOneActivity.id);
|
||||
setCommentableEntityArray([entity]);
|
||||
openRightDrawer(RightDrawerPages.CreateCommentThread);
|
||||
openRightDrawer(RightDrawerPages.CreateActivity);
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -13,21 +13,19 @@ import { selectedRowIdsSelector } from '@/ui/table/states/selectedRowIdsSelector
|
||||
import {
|
||||
ActivityType,
|
||||
CommentableType,
|
||||
useCreateCommentThreadMutation,
|
||||
useCreateActivityMutation,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { GET_COMMENT_THREAD, GET_COMMENT_THREADS_BY_TARGETS } from '../queries';
|
||||
import { GET_ACTIVITIES_BY_TARGETS, GET_ACTIVITY } from '../queries';
|
||||
import { commentableEntityArrayState } from '../states/commentableEntityArrayState';
|
||||
import { viewableCommentThreadIdState } from '../states/viewableCommentThreadIdState';
|
||||
import { viewableActivityIdState } from '../states/viewableActivityIdState';
|
||||
import { CommentableEntity } from '../types/CommentableEntity';
|
||||
|
||||
export function useOpenCreateCommentThreadDrawerForSelectedRowIds() {
|
||||
export function useOpenCreateActivityDrawerForSelectedRowIds() {
|
||||
const { openRightDrawer } = useRightDrawer();
|
||||
const [createCommentThreadMutation] = useCreateCommentThreadMutation();
|
||||
const [createActivityMutation] = useCreateActivityMutation();
|
||||
const currentUser = useRecoilValue(currentUserState);
|
||||
const [, setViewableCommentThreadId] = useRecoilState(
|
||||
viewableCommentThreadIdState,
|
||||
);
|
||||
const [, setViewableActivityId] = useRecoilState(viewableActivityIdState);
|
||||
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
@ -47,13 +45,13 @@ export function useOpenCreateCommentThreadDrawerForSelectedRowIds() {
|
||||
}),
|
||||
);
|
||||
|
||||
createCommentThreadMutation({
|
||||
createActivityMutation({
|
||||
variables: {
|
||||
authorId: currentUser?.id ?? '',
|
||||
commentThreadId: v4(),
|
||||
activityId: v4(),
|
||||
createdAt: new Date().toISOString(),
|
||||
type: ActivityType.Note,
|
||||
commentThreadTargetArray: commentableEntityArray.map((entity) => ({
|
||||
activityTargetArray: commentableEntityArray.map((entity) => ({
|
||||
commentableId: entity.id,
|
||||
commentableType: entity.type,
|
||||
id: v4(),
|
||||
@ -63,14 +61,14 @@ export function useOpenCreateCommentThreadDrawerForSelectedRowIds() {
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
getOperationName(GET_COMMENT_THREAD) ?? '',
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
getOperationName(GET_ACTIVITY) ?? '',
|
||||
getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? '',
|
||||
],
|
||||
onCompleted(data) {
|
||||
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
|
||||
setViewableCommentThreadId(data.createOneCommentThread.id);
|
||||
setViewableActivityId(data.createOneActivity.id);
|
||||
setCommentableEntityArray(commentableEntityArray);
|
||||
openRightDrawer(RightDrawerPages.CreateCommentThread);
|
||||
openRightDrawer(RightDrawerPages.CreateActivity);
|
||||
},
|
||||
});
|
||||
};
|
||||
@ -5,7 +5,7 @@ export const CREATE_COMMENT = gql`
|
||||
$commentId: String!
|
||||
$commentText: String!
|
||||
$authorId: String!
|
||||
$commentThreadId: String!
|
||||
$activityId: String!
|
||||
$createdAt: DateTime!
|
||||
) {
|
||||
createOneComment(
|
||||
@ -14,7 +14,7 @@ export const CREATE_COMMENT = gql`
|
||||
createdAt: $createdAt
|
||||
body: $commentText
|
||||
author: { connect: { id: $authorId } }
|
||||
commentThread: { connect: { id: $commentThreadId } }
|
||||
activity: { connect: { id: $activityId } }
|
||||
}
|
||||
) {
|
||||
id
|
||||
@ -27,32 +27,32 @@ export const CREATE_COMMENT = gql`
|
||||
lastName
|
||||
avatarUrl
|
||||
}
|
||||
commentThreadId
|
||||
activityId
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CREATE_COMMENT_THREAD_WITH_COMMENT = gql`
|
||||
mutation CreateCommentThread(
|
||||
$commentThreadId: String!
|
||||
export const CREATE_ACTIVITY_WITH_COMMENT = gql`
|
||||
mutation CreateActivity(
|
||||
$activityId: String!
|
||||
$body: String
|
||||
$title: String
|
||||
$type: ActivityType!
|
||||
$authorId: String!
|
||||
$createdAt: DateTime!
|
||||
$commentThreadTargetArray: [CommentThreadTargetCreateManyCommentThreadInput!]!
|
||||
$activityTargetArray: [ActivityTargetCreateManyActivityInput!]!
|
||||
) {
|
||||
createOneCommentThread(
|
||||
createOneActivity(
|
||||
data: {
|
||||
id: $commentThreadId
|
||||
id: $activityId
|
||||
createdAt: $createdAt
|
||||
updatedAt: $createdAt
|
||||
author: { connect: { id: $authorId } }
|
||||
body: $body
|
||||
title: $title
|
||||
type: $type
|
||||
commentThreadTargets: {
|
||||
createMany: { data: $commentThreadTargetArray, skipDuplicates: true }
|
||||
activityTargets: {
|
||||
createMany: { data: $activityTargetArray, skipDuplicates: true }
|
||||
}
|
||||
}
|
||||
) {
|
||||
@ -61,11 +61,11 @@ export const CREATE_COMMENT_THREAD_WITH_COMMENT = gql`
|
||||
updatedAt
|
||||
authorId
|
||||
type
|
||||
commentThreadTargets {
|
||||
activityTargets {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
commentThreadId
|
||||
activityId
|
||||
commentableType
|
||||
commentableId
|
||||
}
|
||||
|
||||
@ -1,16 +1,14 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const GET_COMMENT_THREADS_BY_TARGETS = gql`
|
||||
query GetCommentThreadsByTargets(
|
||||
$commentThreadTargetIds: [String!]!
|
||||
$orderBy: [CommentThreadOrderByWithRelationInput!]
|
||||
export const GET_ACTIVITIES_BY_TARGETS = gql`
|
||||
query GetActivitiesByTargets(
|
||||
$activityTargetIds: [String!]!
|
||||
$orderBy: [ActivityOrderByWithRelationInput!]
|
||||
) {
|
||||
findManyCommentThreads(
|
||||
findManyActivities(
|
||||
orderBy: $orderBy
|
||||
where: {
|
||||
commentThreadTargets: {
|
||||
some: { commentableId: { in: $commentThreadTargetIds } }
|
||||
}
|
||||
activityTargets: { some: { commentableId: { in: $activityTargetIds } } }
|
||||
}
|
||||
) {
|
||||
id
|
||||
@ -38,18 +36,18 @@ export const GET_COMMENT_THREADS_BY_TARGETS = gql`
|
||||
avatarUrl
|
||||
}
|
||||
}
|
||||
commentThreadTargets {
|
||||
activityTargets {
|
||||
id
|
||||
commentableId
|
||||
commentableType
|
||||
commentableId
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const GET_COMMENT_THREAD = gql`
|
||||
query GetCommentThread($commentThreadId: String!) {
|
||||
findManyCommentThreads(where: { id: { equals: $commentThreadId } }) {
|
||||
export const GET_ACTIVITY = gql`
|
||||
query GetActivity($activityId: String!) {
|
||||
findManyActivities(where: { id: { equals: $activityId } }) {
|
||||
id
|
||||
createdAt
|
||||
body
|
||||
@ -75,10 +73,10 @@ export const GET_COMMENT_THREAD = gql`
|
||||
avatarUrl
|
||||
}
|
||||
}
|
||||
commentThreadTargets {
|
||||
activityTargets {
|
||||
id
|
||||
commentableId
|
||||
commentableType
|
||||
commentableId
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,22 +1,18 @@
|
||||
import { gql } from '@apollo/client';
|
||||
|
||||
export const ADD_COMMENT_THREAD_TARGETS = gql`
|
||||
mutation AddCommentThreadTargetsOnCommentThread(
|
||||
$commentThreadId: String!
|
||||
$commentThreadTargetInputs: [CommentThreadTargetCreateManyCommentThreadInput!]!
|
||||
export const ADD_ACTIVITY_TARGETS = gql`
|
||||
mutation AddActivityTargetsOnActivity(
|
||||
$activityId: String!
|
||||
$activityTargetInputs: [ActivityTargetCreateManyActivityInput!]!
|
||||
) {
|
||||
updateOneCommentThread(
|
||||
where: { id: $commentThreadId }
|
||||
data: {
|
||||
commentThreadTargets: {
|
||||
createMany: { data: $commentThreadTargetInputs }
|
||||
}
|
||||
}
|
||||
updateOneActivity(
|
||||
where: { id: $activityId }
|
||||
data: { activityTargets: { createMany: { data: $activityTargetInputs } } }
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
commentThreadTargets {
|
||||
activityTargets {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
@ -27,23 +23,21 @@ export const ADD_COMMENT_THREAD_TARGETS = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const REMOVE_COMMENT_THREAD_TARGETS = gql`
|
||||
mutation RemoveCommentThreadTargetsOnCommentThread(
|
||||
$commentThreadId: String!
|
||||
$commentThreadTargetIds: [String!]!
|
||||
export const REMOVE_ACTIVITY_TARGETS = gql`
|
||||
mutation RemoveActivityTargetsOnActivity(
|
||||
$activityId: String!
|
||||
$activityTargetIds: [String!]!
|
||||
) {
|
||||
updateOneCommentThread(
|
||||
where: { id: $commentThreadId }
|
||||
updateOneActivity(
|
||||
where: { id: $activityId }
|
||||
data: {
|
||||
commentThreadTargets: {
|
||||
deleteMany: { id: { in: $commentThreadTargetIds } }
|
||||
}
|
||||
activityTargets: { deleteMany: { id: { in: $activityTargetIds } } }
|
||||
}
|
||||
) {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
commentThreadTargets {
|
||||
activityTargets {
|
||||
id
|
||||
createdAt
|
||||
updatedAt
|
||||
@ -54,23 +48,23 @@ export const REMOVE_COMMENT_THREAD_TARGETS = gql`
|
||||
}
|
||||
`;
|
||||
|
||||
export const DELETE_COMMENT_THREAD = gql`
|
||||
mutation DeleteCommentThread($commentThreadId: String!) {
|
||||
deleteManyCommentThreads(where: { id: { equals: $commentThreadId } }) {
|
||||
export const DELETE_ACTIVITY = gql`
|
||||
mutation DeleteActivity($activityId: String!) {
|
||||
deleteManyActivities(where: { id: { equals: $activityId } }) {
|
||||
count
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const UPDATE_COMMENT_THREAD = gql`
|
||||
mutation UpdateCommentThread(
|
||||
export const UPDATE_ACTIVITY = gql`
|
||||
mutation UpdateActivity(
|
||||
$id: String!
|
||||
$body: String
|
||||
$title: String
|
||||
$type: ActivityType
|
||||
$completedAt: DateTime
|
||||
) {
|
||||
updateOneCommentThread(
|
||||
updateOneActivity(
|
||||
where: { id: $id }
|
||||
data: {
|
||||
body: $body
|
||||
|
||||
@ -0,0 +1,201 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { ActivityBodyEditor } from '@/activities/components/ActivityBodyEditor';
|
||||
import { ActivityComments } from '@/activities/components/ActivityComments';
|
||||
import { ActivityRelationPicker } from '@/activities/components/ActivityRelationPicker';
|
||||
import { ActivityTypeDropdown } from '@/activities/components/ActivityTypeDropdown';
|
||||
import { GET_ACTIVITY } from '@/activities/queries';
|
||||
import { PropertyBox } from '@/ui/editable-field/property-box/components/PropertyBox';
|
||||
import { PropertyBoxItem } from '@/ui/editable-field/property-box/components/PropertyBoxItem';
|
||||
import { useIsMobile } from '@/ui/hooks/useIsMobile';
|
||||
import { IconArrowUpRight } from '@/ui/icon/index';
|
||||
import {
|
||||
useGetActivityQuery,
|
||||
useUpdateActivityMutation,
|
||||
} from '~/generated/graphql';
|
||||
import { debounce } from '~/utils/debounce';
|
||||
|
||||
import { ActivityActionBar } from './ActivityActionBar';
|
||||
|
||||
import '@blocknote/core/style.css';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
justify-content: space-between;
|
||||
overflow-y: auto;
|
||||
`;
|
||||
|
||||
const StyledUpperPartContainer = styled.div`
|
||||
align-items: flex-start;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
gap: ${({ theme }) => theme.spacing(4)};
|
||||
justify-content: flex-start;
|
||||
`;
|
||||
|
||||
const StyledTopContainer = styled.div`
|
||||
align-items: flex-start;
|
||||
align-self: stretch;
|
||||
background: ${({ theme }) => theme.background.secondary};
|
||||
border-bottom: ${({ theme }) =>
|
||||
useIsMobile() ? 'none' : `1px solid ${theme.border.color.medium}`};
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 24px;
|
||||
padding: 24px 24px 24px 48px;
|
||||
`;
|
||||
|
||||
const StyledEditableTitleInput = styled.input`
|
||||
background: transparent;
|
||||
|
||||
border: none;
|
||||
color: ${({ theme }) => theme.font.color.primary};
|
||||
display: flex;
|
||||
flex: 1 0 0;
|
||||
|
||||
flex-direction: column;
|
||||
font-family: Inter;
|
||||
font-size: ${({ theme }) => theme.font.size.xl};
|
||||
font-style: normal;
|
||||
font-weight: ${({ theme }) => theme.font.weight.semiBold};
|
||||
justify-content: center;
|
||||
|
||||
line-height: ${({ theme }) => theme.text.lineHeight.md};
|
||||
outline: none;
|
||||
width: calc(100% - ${({ theme }) => theme.spacing(2)});
|
||||
&::placeholder {
|
||||
color: ${({ theme }) => theme.font.color.light};
|
||||
}
|
||||
`;
|
||||
|
||||
const StyledTopActionsContainer = styled.div`
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
activityId: string;
|
||||
showComment?: boolean;
|
||||
autoFillTitle?: boolean;
|
||||
};
|
||||
|
||||
export function Activity({
|
||||
activityId,
|
||||
showComment = true,
|
||||
autoFillTitle = false,
|
||||
}: OwnProps) {
|
||||
const { data } = useGetActivityQuery({
|
||||
variables: {
|
||||
activityId: activityId ?? '',
|
||||
},
|
||||
skip: !activityId,
|
||||
});
|
||||
const activity = data?.findManyActivities[0];
|
||||
const [hasUserManuallySetTitle, setHasUserManuallySetTitle] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const [title, setTitle] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!hasUserManuallySetTitle) {
|
||||
setTitle(activity?.title ?? '');
|
||||
}
|
||||
}, [setTitle, activity?.title, hasUserManuallySetTitle]);
|
||||
|
||||
const [updateActivityMutation] = useUpdateActivityMutation();
|
||||
|
||||
const debounceUpdateTitle = useMemo(() => {
|
||||
function updateTitle(title: string) {
|
||||
if (activity) {
|
||||
updateActivityMutation({
|
||||
variables: {
|
||||
id: activityId,
|
||||
title: title ?? '',
|
||||
},
|
||||
refetchQueries: [getOperationName(GET_ACTIVITY) ?? ''],
|
||||
optimisticResponse: {
|
||||
__typename: 'Mutation',
|
||||
updateOneActivity: {
|
||||
__typename: 'Activity',
|
||||
id: activityId,
|
||||
title: title,
|
||||
type: activity.type,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
return debounce(updateTitle, 200);
|
||||
}, [activityId, updateActivityMutation, activity]);
|
||||
|
||||
function updateTitleFromBody(body: string) {
|
||||
const parsedTitle = JSON.parse(body)[0]?.content[0]?.text;
|
||||
if (!hasUserManuallySetTitle && autoFillTitle) {
|
||||
setTitle(parsedTitle);
|
||||
debounceUpdateTitle(parsedTitle);
|
||||
}
|
||||
}
|
||||
|
||||
if (!activity) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<StyledContainer>
|
||||
<StyledUpperPartContainer>
|
||||
<StyledTopContainer>
|
||||
<StyledTopActionsContainer>
|
||||
<ActivityTypeDropdown activity={activity} />
|
||||
<ActivityActionBar activityId={activity?.id ?? ''} />
|
||||
</StyledTopActionsContainer>
|
||||
<StyledEditableTitleInput
|
||||
autoFocus
|
||||
placeholder={`${activity.type} title (optional)`}
|
||||
onChange={(event) => {
|
||||
setHasUserManuallySetTitle(true);
|
||||
setTitle(event.target.value);
|
||||
debounceUpdateTitle(event.target.value);
|
||||
}}
|
||||
value={title ?? ''}
|
||||
/>
|
||||
<PropertyBox>
|
||||
<PropertyBoxItem
|
||||
icon={<IconArrowUpRight />}
|
||||
value={
|
||||
<ActivityRelationPicker
|
||||
activity={{
|
||||
id: activity.id,
|
||||
activityTargets: activity.activityTargets ?? [],
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label="Relations"
|
||||
/>
|
||||
</PropertyBox>
|
||||
</StyledTopContainer>
|
||||
<ActivityBodyEditor
|
||||
activity={activity}
|
||||
onChange={updateTitleFromBody}
|
||||
/>
|
||||
</StyledUpperPartContainer>
|
||||
{showComment && (
|
||||
<ActivityComments
|
||||
activity={{
|
||||
id: activity.id,
|
||||
comments: activity.comments ?? [],
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</StyledContainer>
|
||||
);
|
||||
}
|
||||
@ -3,13 +3,13 @@ import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
import { useRecoilState } from 'recoil';
|
||||
|
||||
import { GET_COMMENT_THREADS_BY_TARGETS } from '@/activities/queries';
|
||||
import { GET_ACTIVITIES_BY_TARGETS } from '@/activities/queries';
|
||||
import { GET_COMPANIES } from '@/companies/queries';
|
||||
import { GET_PEOPLE } from '@/people/queries';
|
||||
import { Button, ButtonVariant } from '@/ui/button/components/Button';
|
||||
import { IconTrash } from '@/ui/icon';
|
||||
import { isRightDrawerOpenState } from '@/ui/right-drawer/states/isRightDrawerOpenState';
|
||||
import { useDeleteCommentThreadMutation } from '~/generated/graphql';
|
||||
import { useDeleteActivityMutation } from '~/generated/graphql';
|
||||
|
||||
const StyledContainer = styled.div`
|
||||
color: ${({ theme }) => theme.font.color.tertiary};
|
||||
@ -17,21 +17,21 @@ const StyledContainer = styled.div`
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
commentThreadId: string;
|
||||
activityId: string;
|
||||
};
|
||||
|
||||
export function CommentThreadActionBar({ commentThreadId }: OwnProps) {
|
||||
export function ActivityActionBar({ activityId }: OwnProps) {
|
||||
const theme = useTheme();
|
||||
const [createCommentMutation] = useDeleteCommentThreadMutation();
|
||||
const [createCommentMutation] = useDeleteActivityMutation();
|
||||
const [, setIsRightDrawerOpen] = useRecoilState(isRightDrawerOpenState);
|
||||
|
||||
function deleteCommentThread() {
|
||||
function deleteActivity() {
|
||||
createCommentMutation({
|
||||
variables: { commentThreadId },
|
||||
variables: { activityId },
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMPANIES) ?? '',
|
||||
getOperationName(GET_PEOPLE) ?? '',
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? '',
|
||||
],
|
||||
});
|
||||
setIsRightDrawerOpen(false);
|
||||
@ -43,7 +43,7 @@ export function CommentThreadActionBar({ commentThreadId }: OwnProps) {
|
||||
icon={
|
||||
<IconTrash size={theme.icon.size.sm} stroke={theme.icon.stroke.md} />
|
||||
}
|
||||
onClick={deleteCommentThread}
|
||||
onClick={deleteActivity}
|
||||
variant={ButtonVariant.Tertiary}
|
||||
/>
|
||||
</StyledContainer>
|
||||
@ -1,34 +0,0 @@
|
||||
import { CommentThreadEditor } from '@/activities/components/CommentThreadEditor';
|
||||
import { useGetCommentThreadQuery } from '~/generated/graphql';
|
||||
|
||||
import '@blocknote/core/style.css';
|
||||
|
||||
type OwnProps = {
|
||||
commentThreadId: string;
|
||||
showComment?: boolean;
|
||||
autoFillTitle?: boolean;
|
||||
};
|
||||
|
||||
export function CommentThread({
|
||||
commentThreadId,
|
||||
showComment = true,
|
||||
autoFillTitle = false,
|
||||
}: OwnProps) {
|
||||
const { data } = useGetCommentThreadQuery({
|
||||
variables: {
|
||||
commentThreadId: commentThreadId ?? '',
|
||||
},
|
||||
skip: !commentThreadId,
|
||||
});
|
||||
const commentThread = data?.findManyCommentThreads[0];
|
||||
|
||||
return commentThread ? (
|
||||
<CommentThreadEditor
|
||||
commentThread={commentThread}
|
||||
showComment={showComment}
|
||||
autoFillTitle={autoFillTitle}
|
||||
/>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
}
|
||||
@ -1,22 +1,22 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { viewableCommentThreadIdState } from '@/activities/states/viewableCommentThreadIdState';
|
||||
import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState';
|
||||
import { RightDrawerBody } from '@/ui/right-drawer/components/RightDrawerBody';
|
||||
import { RightDrawerPage } from '@/ui/right-drawer/components/RightDrawerPage';
|
||||
import { RightDrawerTopBar } from '@/ui/right-drawer/components/RightDrawerTopBar';
|
||||
|
||||
import { CommentThread } from '../CommentThread';
|
||||
import { Activity } from '../Activity';
|
||||
|
||||
export function RightDrawerCreateCommentThread() {
|
||||
const commentThreadId = useRecoilValue(viewableCommentThreadIdState);
|
||||
export function RightDrawerCreateActivity() {
|
||||
const activityId = useRecoilValue(viewableActivityIdState);
|
||||
|
||||
return (
|
||||
<RightDrawerPage>
|
||||
<RightDrawerTopBar />
|
||||
<RightDrawerBody>
|
||||
{commentThreadId && (
|
||||
<CommentThread
|
||||
commentThreadId={commentThreadId}
|
||||
{activityId && (
|
||||
<Activity
|
||||
activityId={activityId}
|
||||
showComment={false}
|
||||
autoFillTitle={true}
|
||||
/>
|
||||
@ -1,20 +1,20 @@
|
||||
import { useRecoilValue } from 'recoil';
|
||||
|
||||
import { viewableCommentThreadIdState } from '@/activities/states/viewableCommentThreadIdState';
|
||||
import { viewableActivityIdState } from '@/activities/states/viewableActivityIdState';
|
||||
import { RightDrawerBody } from '@/ui/right-drawer/components/RightDrawerBody';
|
||||
import { RightDrawerPage } from '@/ui/right-drawer/components/RightDrawerPage';
|
||||
import { RightDrawerTopBar } from '@/ui/right-drawer/components/RightDrawerTopBar';
|
||||
|
||||
import { CommentThread } from '../CommentThread';
|
||||
import { Activity } from '../Activity';
|
||||
|
||||
export function RightDrawerEditCommentThread() {
|
||||
const commentThreadId = useRecoilValue(viewableCommentThreadIdState);
|
||||
export function RightDrawerEditActivity() {
|
||||
const activityId = useRecoilValue(viewableActivityIdState);
|
||||
|
||||
return (
|
||||
<RightDrawerPage>
|
||||
<RightDrawerTopBar />
|
||||
<RightDrawerBody>
|
||||
{commentThreadId && <CommentThread commentThreadId={commentThreadId} />}
|
||||
{activityId && <Activity activityId={activityId} />}
|
||||
</RightDrawerBody>
|
||||
</RightDrawerPage>
|
||||
);
|
||||
@ -3,6 +3,6 @@ import { atom } from 'recoil';
|
||||
import { CommentableEntity } from '../types/CommentableEntity';
|
||||
|
||||
export const commentableEntityArrayState = atom<CommentableEntity[]>({
|
||||
key: 'comments/commentable-entity-array',
|
||||
key: 'activities/commentable-entity-array',
|
||||
default: [],
|
||||
});
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
export const viewableActivityIdState = atom<string | null>({
|
||||
key: 'activities/viewable-activity-id',
|
||||
default: null,
|
||||
});
|
||||
@ -1,6 +0,0 @@
|
||||
import { atom } from 'recoil';
|
||||
|
||||
export const viewableCommentThreadIdState = atom<string | null>({
|
||||
key: 'comments/viewable-comment-thread-id',
|
||||
default: null,
|
||||
});
|
||||
@ -2,16 +2,16 @@ import React from 'react';
|
||||
import { useTheme } from '@emotion/react';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { CommentThreadCreateButton } from '@/activities/components/CommentThreadCreateButton';
|
||||
import { useOpenCreateCommentThreadDrawer } from '@/activities/hooks/useOpenCreateCommentThreadDrawer';
|
||||
import { ActivityCreateButton } from '@/activities/components/ActivityCreateButton';
|
||||
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
|
||||
import { ActivityForDrawer } from '@/activities/types/ActivityForDrawer';
|
||||
import { CommentableEntity } from '@/activities/types/CommentableEntity';
|
||||
import { CommentThreadForDrawer } from '@/activities/types/CommentThreadForDrawer';
|
||||
import { useIsMobile } from '@/ui/hooks/useIsMobile';
|
||||
import { IconCircleDot } from '@/ui/icon';
|
||||
import {
|
||||
ActivityType,
|
||||
SortOrder,
|
||||
useGetCommentThreadsByTargetsQuery,
|
||||
useGetActivitiesByTargetsQuery,
|
||||
} from '~/generated/graphql';
|
||||
|
||||
import { TimelineActivity } from './TimelineActivity';
|
||||
@ -96,9 +96,9 @@ const StyledStartIcon = styled.div`
|
||||
export function Timeline({ entity }: { entity: CommentableEntity }) {
|
||||
const theme = useTheme();
|
||||
|
||||
const { data: queryResult, loading } = useGetCommentThreadsByTargetsQuery({
|
||||
const { data: queryResult, loading } = useGetActivitiesByTargetsQuery({
|
||||
variables: {
|
||||
commentThreadTargetIds: [entity.id],
|
||||
activityTargetIds: [entity.id],
|
||||
orderBy: [
|
||||
{
|
||||
createdAt: SortOrder.Desc,
|
||||
@ -107,21 +107,20 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
|
||||
},
|
||||
});
|
||||
|
||||
const openCreateCommandThread = useOpenCreateCommentThreadDrawer();
|
||||
const openCreateCommandThread = useOpenCreateActivityDrawer();
|
||||
|
||||
const commentThreads: CommentThreadForDrawer[] =
|
||||
queryResult?.findManyCommentThreads ?? [];
|
||||
const activities: ActivityForDrawer[] = queryResult?.findManyActivities ?? [];
|
||||
|
||||
if (loading) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
if (!commentThreads.length) {
|
||||
if (!activities.length) {
|
||||
return (
|
||||
<StyledTimelineEmptyContainer>
|
||||
<StyledEmptyTimelineTitle>No activity yet</StyledEmptyTimelineTitle>
|
||||
<StyledEmptyTimelineSubTitle>Create one:</StyledEmptyTimelineSubTitle>
|
||||
<CommentThreadCreateButton
|
||||
<ActivityCreateButton
|
||||
onNoteClick={() => openCreateCommandThread(entity, ActivityType.Note)}
|
||||
onTaskClick={() => openCreateCommandThread(entity, ActivityType.Task)}
|
||||
/>
|
||||
@ -132,17 +131,14 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
|
||||
return (
|
||||
<StyledMainContainer>
|
||||
<StyledTopActionBar>
|
||||
<CommentThreadCreateButton
|
||||
<ActivityCreateButton
|
||||
onNoteClick={() => openCreateCommandThread(entity, ActivityType.Note)}
|
||||
onTaskClick={() => openCreateCommandThread(entity, ActivityType.Task)}
|
||||
/>
|
||||
</StyledTopActionBar>
|
||||
<StyledTimelineContainer>
|
||||
{commentThreads.map((commentThread) => (
|
||||
<TimelineActivity
|
||||
key={commentThread.id}
|
||||
commentThread={commentThread}
|
||||
/>
|
||||
{activities.map((activity) => (
|
||||
<TimelineActivity key={activity.id} activity={activity} />
|
||||
))}
|
||||
<StyledStartIcon>
|
||||
<IconCircleDot size={theme.icon.size.lg} />
|
||||
|
||||
@ -3,14 +3,11 @@ import { Tooltip } from 'react-tooltip';
|
||||
import { getOperationName } from '@apollo/client/utilities';
|
||||
import styled from '@emotion/styled';
|
||||
|
||||
import { useOpenCommentThreadRightDrawer } from '@/activities/hooks/useOpenCommentThreadRightDrawer';
|
||||
import { GET_COMMENT_THREADS_BY_TARGETS } from '@/activities/queries';
|
||||
import { useOpenActivityRightDrawer } from '@/activities/hooks/useOpenActivityRightDrawer';
|
||||
import { GET_ACTIVITIES_BY_TARGETS } from '@/activities/queries';
|
||||
import { IconNotes } from '@/ui/icon';
|
||||
import { OverflowingTextWithTooltip } from '@/ui/tooltip/OverflowingTextWithTooltip';
|
||||
import {
|
||||
CommentThread,
|
||||
useUpdateCommentThreadMutation,
|
||||
} from '~/generated/graphql';
|
||||
import { Activity, useUpdateActivityMutation } from '~/generated/graphql';
|
||||
import {
|
||||
beautifyExactDate,
|
||||
beautifyPastDateRelativeToNow,
|
||||
@ -115,35 +112,31 @@ const StyledTimelineItemContainer = styled.div`
|
||||
`;
|
||||
|
||||
type OwnProps = {
|
||||
commentThread: Pick<
|
||||
CommentThread,
|
||||
activity: Pick<
|
||||
Activity,
|
||||
'id' | 'title' | 'body' | 'createdAt' | 'completedAt' | 'type'
|
||||
> & { author: Pick<CommentThread['author'], 'displayName'> };
|
||||
> & { author: Pick<Activity['author'], 'displayName'> };
|
||||
};
|
||||
|
||||
export function TimelineActivity({ commentThread }: OwnProps) {
|
||||
const beautifiedCreatedAt = beautifyPastDateRelativeToNow(
|
||||
commentThread.createdAt,
|
||||
);
|
||||
const exactCreatedAt = beautifyExactDate(commentThread.createdAt);
|
||||
const body = JSON.parse(commentThread.body ?? '{}')[0]?.content[0]?.text;
|
||||
export function TimelineActivity({ activity }: OwnProps) {
|
||||
const beautifiedCreatedAt = beautifyPastDateRelativeToNow(activity.createdAt);
|
||||
const exactCreatedAt = beautifyExactDate(activity.createdAt);
|
||||
const body = JSON.parse(activity.body ?? '{}')[0]?.content[0]?.text;
|
||||
|
||||
const openCommentThreadRightDrawer = useOpenCommentThreadRightDrawer();
|
||||
const [updateCommentThreadMutation] = useUpdateCommentThreadMutation();
|
||||
const openActivityRightDrawer = useOpenActivityRightDrawer();
|
||||
const [updateActivityMutation] = useUpdateActivityMutation();
|
||||
|
||||
const handleActivityCompletionChange = useCallback(
|
||||
(value: boolean) => {
|
||||
updateCommentThreadMutation({
|
||||
updateActivityMutation({
|
||||
variables: {
|
||||
id: commentThread.id,
|
||||
id: activity.id,
|
||||
completedAt: value ? new Date().toISOString() : null,
|
||||
},
|
||||
refetchQueries: [
|
||||
getOperationName(GET_COMMENT_THREADS_BY_TARGETS) ?? '',
|
||||
],
|
||||
refetchQueries: [getOperationName(GET_ACTIVITIES_BY_TARGETS) ?? ''],
|
||||
});
|
||||
},
|
||||
[commentThread, updateCommentThreadMutation],
|
||||
[activity, updateActivityMutation],
|
||||
);
|
||||
|
||||
return (
|
||||
@ -153,14 +146,14 @@ export function TimelineActivity({ commentThread }: OwnProps) {
|
||||
<IconNotes />
|
||||
</StyledIconContainer>
|
||||
<StyledItemTitleContainer>
|
||||
<span>{commentThread.author.displayName}</span>
|
||||
created a {commentThread.type.toLowerCase()}
|
||||
<span>{activity.author.displayName}</span>
|
||||
created a note created a {activity.type.toLowerCase()}
|
||||
</StyledItemTitleContainer>
|
||||
<StyledItemTitleDate id={`id-${commentThread.id}`}>
|
||||
<StyledItemTitleDate id={`id-${activity.id}`}>
|
||||
{beautifiedCreatedAt} ago
|
||||
</StyledItemTitleDate>
|
||||
<StyledTooltip
|
||||
anchorSelect={`#id-${commentThread.id}`}
|
||||
anchorSelect={`#id-${activity.id}`}
|
||||
content={exactCreatedAt}
|
||||
clickable
|
||||
noArrow
|
||||
@ -171,13 +164,11 @@ export function TimelineActivity({ commentThread }: OwnProps) {
|
||||
<StyledVerticalLine></StyledVerticalLine>
|
||||
</StyledVerticalLineContainer>
|
||||
<StyledCardContainer>
|
||||
<StyledCard
|
||||
onClick={() => openCommentThreadRightDrawer(commentThread.id)}
|
||||
>
|
||||
<StyledCard onClick={() => openActivityRightDrawer(activity.id)}>
|
||||
<TimelineActivityTitle
|
||||
title={commentThread.title ?? ''}
|
||||
completed={!!commentThread.completedAt}
|
||||
type={commentThread.type}
|
||||
title={activity.title ?? ''}
|
||||
completed={!!activity.completedAt}
|
||||
type={activity.type}
|
||||
onCompletionChange={handleActivityCompletionChange}
|
||||
/>
|
||||
<StyledCardContent>
|
||||
|
||||
4
front/src/modules/activities/types/ActivityForDrawer.ts
Normal file
4
front/src/modules/activities/types/ActivityForDrawer.ts
Normal file
@ -0,0 +1,4 @@
|
||||
import { GetActivitiesByTargetsQuery } from '~/generated/graphql';
|
||||
|
||||
export type ActivityForDrawer =
|
||||
GetActivitiesByTargetsQuery['findManyActivities'][0];
|
||||
@ -1,5 +1,3 @@
|
||||
import { CommentThreadForDrawer } from './CommentThreadForDrawer';
|
||||
import { ActivityForDrawer } from './ActivityForDrawer';
|
||||
|
||||
export type CommentForDrawer = NonNullable<
|
||||
CommentThreadForDrawer['comments']
|
||||
>[0];
|
||||
export type CommentForDrawer = NonNullable<ActivityForDrawer['comments']>[0];
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
import { GetCommentThreadsByTargetsQuery } from '~/generated/graphql';
|
||||
|
||||
export type CommentThreadForDrawer =
|
||||
GetCommentThreadsByTargetsQuery['findManyCommentThreads'][0];
|
||||
Reference in New Issue
Block a user