Begin auto-save on edit mode

This commit is contained in:
Félix Malfait
2023-07-08 15:14:23 +02:00
parent 7b20932648
commit 04ef9830ab
6 changed files with 156 additions and 14 deletions

View File

@@ -2615,9 +2615,9 @@ export type UserCreateWithoutCommentThreadInput = {
disabled?: InputMaybe<Scalars['Boolean']>;
email: Scalars['String'];
emailVerified?: InputMaybe<Scalars['Boolean']>;
firstName: Scalars['String'];
firstName?: InputMaybe<Scalars['String']>;
id?: InputMaybe<Scalars['String']>;
lastName: Scalars['String'];
lastName?: InputMaybe<Scalars['String']>;
lastSeen?: InputMaybe<Scalars['DateTime']>;
locale: Scalars['String'];
metadata?: InputMaybe<Scalars['JSON']>;
@@ -2759,9 +2759,9 @@ export type UserUpdateWithoutCommentThreadInput = {
disabled?: InputMaybe<BoolFieldUpdateOperationsInput>;
email?: InputMaybe<StringFieldUpdateOperationsInput>;
emailVerified?: InputMaybe<BoolFieldUpdateOperationsInput>;
firstName?: InputMaybe<StringFieldUpdateOperationsInput>;
firstName?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
id?: InputMaybe<StringFieldUpdateOperationsInput>;
lastName?: InputMaybe<StringFieldUpdateOperationsInput>;
lastName?: InputMaybe<NullableStringFieldUpdateOperationsInput>;
lastSeen?: InputMaybe<NullableDateTimeFieldUpdateOperationsInput>;
locale?: InputMaybe<StringFieldUpdateOperationsInput>;
metadata?: InputMaybe<Scalars['JSON']>;
@@ -3079,6 +3079,22 @@ export type DeleteCommentThreadMutationVariables = Exact<{
export type DeleteCommentThreadMutation = { __typename?: 'Mutation', deleteManyCommentThreads: { __typename?: 'AffectedRows', count: number } };
export type UpdateCommentThreadTitleMutationVariables = Exact<{
commentThreadId: Scalars['String'];
commentThreadTitle?: InputMaybe<Scalars['String']>;
}>;
export type UpdateCommentThreadTitleMutation = { __typename?: 'Mutation', updateOneCommentThread: { __typename?: 'CommentThread', id: string } };
export type UpdateCommentThreadBodyMutationVariables = Exact<{
commentThreadId: Scalars['String'];
commentThreadBody?: InputMaybe<Scalars['String']>;
}>;
export type UpdateCommentThreadBodyMutation = { __typename?: 'Mutation', updateOneCommentThread: { __typename?: 'CommentThread', id: string } };
export type GetCompaniesQueryVariables = Exact<{
orderBy?: InputMaybe<Array<CompanyOrderByWithRelationInput> | CompanyOrderByWithRelationInput>;
where?: InputMaybe<CompanyWhereInput>;
@@ -3857,6 +3873,80 @@ export function useDeleteCommentThreadMutation(baseOptions?: Apollo.MutationHook
export type DeleteCommentThreadMutationHookResult = ReturnType<typeof useDeleteCommentThreadMutation>;
export type DeleteCommentThreadMutationResult = Apollo.MutationResult<DeleteCommentThreadMutation>;
export type DeleteCommentThreadMutationOptions = Apollo.BaseMutationOptions<DeleteCommentThreadMutation, DeleteCommentThreadMutationVariables>;
export const UpdateCommentThreadTitleDocument = gql`
mutation UpdateCommentThreadTitle($commentThreadId: String!, $commentThreadTitle: String) {
updateOneCommentThread(
where: {id: $commentThreadId}
data: {title: {set: $commentThreadTitle}}
) {
id
}
}
`;
export type UpdateCommentThreadTitleMutationFn = Apollo.MutationFunction<UpdateCommentThreadTitleMutation, UpdateCommentThreadTitleMutationVariables>;
/**
* __useUpdateCommentThreadTitleMutation__
*
* To run a mutation, you first call `useUpdateCommentThreadTitleMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateCommentThreadTitleMutation` 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 [updateCommentThreadTitleMutation, { data, loading, error }] = useUpdateCommentThreadTitleMutation({
* variables: {
* commentThreadId: // value for 'commentThreadId'
* commentThreadTitle: // value for 'commentThreadTitle'
* },
* });
*/
export function useUpdateCommentThreadTitleMutation(baseOptions?: Apollo.MutationHookOptions<UpdateCommentThreadTitleMutation, UpdateCommentThreadTitleMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<UpdateCommentThreadTitleMutation, UpdateCommentThreadTitleMutationVariables>(UpdateCommentThreadTitleDocument, options);
}
export type UpdateCommentThreadTitleMutationHookResult = ReturnType<typeof useUpdateCommentThreadTitleMutation>;
export type UpdateCommentThreadTitleMutationResult = Apollo.MutationResult<UpdateCommentThreadTitleMutation>;
export type UpdateCommentThreadTitleMutationOptions = Apollo.BaseMutationOptions<UpdateCommentThreadTitleMutation, UpdateCommentThreadTitleMutationVariables>;
export const UpdateCommentThreadBodyDocument = gql`
mutation UpdateCommentThreadBody($commentThreadId: String!, $commentThreadBody: String) {
updateOneCommentThread(
where: {id: $commentThreadId}
data: {body: {set: $commentThreadBody}}
) {
id
}
}
`;
export type UpdateCommentThreadBodyMutationFn = Apollo.MutationFunction<UpdateCommentThreadBodyMutation, UpdateCommentThreadBodyMutationVariables>;
/**
* __useUpdateCommentThreadBodyMutation__
*
* To run a mutation, you first call `useUpdateCommentThreadBodyMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useUpdateCommentThreadBodyMutation` 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 [updateCommentThreadBodyMutation, { data, loading, error }] = useUpdateCommentThreadBodyMutation({
* variables: {
* commentThreadId: // value for 'commentThreadId'
* commentThreadBody: // value for 'commentThreadBody'
* },
* });
*/
export function useUpdateCommentThreadBodyMutation(baseOptions?: Apollo.MutationHookOptions<UpdateCommentThreadBodyMutation, UpdateCommentThreadBodyMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<UpdateCommentThreadBodyMutation, UpdateCommentThreadBodyMutationVariables>(UpdateCommentThreadBodyDocument, options);
}
export type UpdateCommentThreadBodyMutationHookResult = ReturnType<typeof useUpdateCommentThreadBodyMutation>;
export type UpdateCommentThreadBodyMutationResult = Apollo.MutationResult<UpdateCommentThreadBodyMutation>;
export type UpdateCommentThreadBodyMutationOptions = Apollo.BaseMutationOptions<UpdateCommentThreadBodyMutation, UpdateCommentThreadBodyMutationVariables>;
export const GetCompaniesDocument = gql`
query GetCompanies($orderBy: [CompanyOrderByWithRelationInput!], $where: CompanyWhereInput) {
companies: findManyCompany(orderBy: $orderBy, where: $where) {

View File

@@ -7,7 +7,11 @@ import styled from '@emotion/styled';
import { PropertyBox } from '@/ui/components/property-box/PropertyBox';
import { PropertyBoxItem } from '@/ui/components/property-box/PropertyBoxItem';
import { IconArrowUpRight } from '@/ui/icons/index';
import { useGetCommentThreadQuery } from '~/generated/graphql';
import {
useGetCommentThreadQuery,
useUpdateCommentThreadBodyMutation,
useUpdateCommentThreadTitleMutation,
} from '~/generated/graphql';
import { Comments } from './Comments';
import { CommentThreadRelationPicker } from './CommentThreadRelationPicker';
@@ -78,15 +82,23 @@ export function CommentThreadEditMode({
});
const [editorReady, setEditorReady] = useState(false);
const [title, setTitle] = useState('');
console.log();
const [updateCommentThreadTitleMutation] =
useUpdateCommentThreadTitleMutation();
const [updateCommentThreadBodyMutation] =
useUpdateCommentThreadBodyMutation();
const editor: BlockNoteEditor | null = useBlockNote({
theme: useTheme().name === 'light' ? 'light' : 'dark',
initialContent: undefined,
onEditorContentChange: (editor) => {
// TODO: save operation here
console.log('save');
updateCommentThreadBodyMutation({
variables: {
commentThreadId: commentThreadId,
commentThreadBody: JSON.stringify(editor.topLevelBlocks) ?? '',
},
});
},
onEditorReady: (editor) => {
setEditorReady(true);
@@ -98,15 +110,28 @@ export function CommentThreadEditMode({
const newContent = JSON.parse(data.findManyCommentThreads[0].body);
editor?.replaceBlocks(editor.topLevelBlocks, newContent);
}
if (data?.findManyCommentThreads[0]?.title) {
setTitle(data.findManyCommentThreads[0].title);
}
}, [data, editor, editorReady]);
function onTitleChange(e: React.ChangeEvent<HTMLInputElement>) {
setTitle(e.target.value);
updateCommentThreadTitleMutation({
variables: {
commentThreadId: commentThreadId,
commentThreadTitle: e.target.value ?? '',
},
});
}
if (typeof data?.findManyCommentThreads[0] === 'undefined') {
return null;
}
const commentThread = data?.findManyCommentThreads[0];
// TODO : prevent editor from creating loops
// TODO : check editor performance (loops/ double save)
return (
<StyledContainer>
@@ -114,7 +139,8 @@ export function CommentThreadEditMode({
<CommentThreadTypeDropdown />
<StyledEditableTitleInput
placeholder="Note title (optional)"
defaultValue={commentThread.title ?? ''}
onChange={onTitleChange}
value={title}
/>
<PropertyBox>
<PropertyBoxItem

View File

@@ -11,7 +11,7 @@ export function CommentThreadTypeDropdown() {
];
const handleSelect = (selectedOption: DropdownOptionType) => {
console.log(`You selected: ${selectedOption.label}`);
// console.log(`You selected: ${selectedOption.label}`);
};
return <DropdownButton options={options} onSelection={handleSelect} />;

View File

@@ -222,8 +222,6 @@ export function Timeline({ entity }: { entity: CommentableEntity }) {
);
const exactCreatedAt = beautifyExactDate(commentThread.createdAt);
console.log(JSON.parse(commentThread.body ?? '')[0].content[0]?.text);
return (
<React.Fragment key={commentThread.id}>
<StyledTimelineItemContainer>

View File

@@ -68,3 +68,31 @@ export const DELETE_COMMENT_THREAD = gql`
}
}
`;
export const UPDATE_COMMENT_THREAD_TITLE = gql`
mutation UpdateCommentThreadTitle(
$commentThreadId: String!
$commentThreadTitle: String
) {
updateOneCommentThread(
where: { id: $commentThreadId }
data: { title: { set: $commentThreadTitle } }
) {
id
}
}
`;
export const UPDATE_COMMENT_THREAD_BODY = gql`
mutation UpdateCommentThreadBody(
$commentThreadId: String!
$commentThreadBody: String
) {
updateOneCommentThread(
where: { id: $commentThreadId }
data: { body: { set: $commentThreadBody } }
) {
id
}
}
`;

View File

@@ -57,7 +57,7 @@ export class CommentThreadResolver {
const createdCommentThread = await this.commentThreadService.create({
data: {
...args.data,
// ...{ comments: { createMany: { data: newCommentData } } },
//...{ comments: { createMany: { data: newCommentData } } },
...{ workspace: { connect: { id: workspace.id } } },
},
select: prismaSelect.value,