Skip to content

Commit

Permalink
feat: more work on ui notes
Browse files Browse the repository at this point in the history
  • Loading branch information
tomer-shvadron committed Oct 30, 2024
1 parent 21ffdd4 commit f6f5fea
Show file tree
Hide file tree
Showing 16 changed files with 153 additions and 17 deletions.
4 changes: 3 additions & 1 deletion apps/backoffice-v2/src/pages/Entity/Entity.page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { BlocksVariant } from '@/lib/blocks/variants/BlocksVariant/BlocksVariant
import { useEntityLogic } from '@/pages/Entity/hooks/useEntityLogic/useEntityLogic';

export const Entity = () => {
const { workflow, selectedEntity } = useEntityLogic();
const { workflow, notes, selectedEntity } = useEntityLogic();
const { isNotesOpen } = useNotes();

if (!workflow) {
Expand All @@ -21,6 +21,7 @@ export const Entity = () => {
<Case key={workflow?.id}>
{/* Reject and approve header */}
<Case.Actions
numberOfNotes={notes?.length ?? 0}
id={workflow?.id}
fullName={selectedEntity?.name}
avatarUrl={selectedEntity?.avatarUrl}
Expand All @@ -46,6 +47,7 @@ export const Entity = () => {
<AnimatePresence>
{isNotesOpen && (
<Notes
notes={notes}
displayName={workflow.entity.name}
entityId={workflow.entity.id}
entityType={`Business`}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { ActionsVariant } from '@/pages/Entity/components/Case/actions-variants/
export const Actions: FunctionComponent<IActionsProps> = ({
id,
fullName,
numberOfNotes,
showResolutionButtons,
}) => {
const {
Expand Down Expand Up @@ -85,7 +86,16 @@ export const Actions: FunctionComponent<IActionsProps> = ({
)}
<div className={`flex items-center space-x-2`}>
<span className={`me-2 text-sm leading-6`}>Notes</span>
<SquarePen className={`cursor-pointer d-5`} onClick={toggleNotes} />
<div className={`relative flex`}>
<SquarePen className={`cursor-pointer d-5`} onClick={toggleNotes} />
{numberOfNotes > 0 && (
<div
className={`absolute left-3 top-3 rounded-full bg-[#007AFF] ps-1 text-xs font-bold text-white d-4`}
>
{numberOfNotes}
</div>
)}
</div>
</div>
</div>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface IActionsProps {
id: string;
fullName: string;
avatarUrl: string;
numberOfNotes: number;
showResolutionButtons?: boolean;
workflow: TWorkflowById;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,26 @@ import { motion } from 'framer-motion';
import { TextArea } from '@ballerine/ui';
import { Loader2, X } from 'lucide-react';

import { NoteableType } from './types';
import { ctw } from '@/common/utils/ctw/ctw';
import { useNotes } from '@/domains/notes/hooks/useNotes';
import { Button } from '@/common/components/atoms/Button/Button';
import { useNotesLogic } from '@/pages/Entity/components/Notes/hooks/useNotesLogic';

export const Notes = ({
notes,
displayName,
entityId,
entityType,
noteableId,
noteableType,
}: {
notes: any[];
displayName: string;
entityId: string;
entityType: 'Business' | 'EndUser';
noteableId: string;
noteableType: 'Report' | 'Alert' | 'Workflow';
noteableType: NoteableType;
}) => {
const { toggleNotes } = useNotes();
const { note, onNoteChange, onSubmit } = useNotesLogic();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import { z } from 'zod';
import { apiClient } from '@/common/api-client/api-client';

import { Method } from '@/common/enums';
import { apiClient } from '@/common/api-client/api-client';
import { NoteableType } from '@/pages/Entity/components/Notes/types';
import { handleZodError } from '@/common/utils/handle-zod-error/handle-zod-error';
import { NoteSchema } from '@/pages/Entity/components/Notes/hooks/schemas/note-schema';

export const createNote = async ({
entityId,
Expand All @@ -14,7 +17,7 @@ export const createNote = async ({
entityId: string;
entityType: 'Business' | 'EndUser';
noteableId: string;
noteableType: 'Report' | 'Alert' | 'Workflow';
noteableType: NoteableType;
content: string;
parentNoteId: string | null;
}) => {
Expand All @@ -34,3 +37,19 @@ export const createNote = async ({

return handleZodError(error, note);
};

export const getNotesByNotable = async ({
noteableId,
noteableType,
}: {
noteableId: string;
noteableType: NoteableType;
}) => {
const [note, error] = await apiClient({
endpoint: `../external/notes/${noteableType}/${noteableId}`,
method: Method.GET,
schema: z.array(NoteSchema),
});

return handleZodError(error, note);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,9 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';

import { HttpError } from '@/common/errors/http-error';
import { createNote } from '@/pages/Entity/components/Notes/hooks/fetchers';
import { NoteableType } from '@/pages/Entity/components/Notes/types';

export const useCreateNoteMutation = ({
onSuccess,
}: {
onSuccess?: <TData>(data: TData) => void;
}) => {
export const useCreateNoteMutation = (onSuccess?: <TData>(data: TData) => void) => {
const queryClient = useQueryClient();

return useMutation({
Expand All @@ -25,7 +22,7 @@ export const useCreateNoteMutation = ({
entityId: string;
entityType: 'Business' | 'EndUser';
noteableId: string;
noteableType: 'Report' | 'Alert' | 'Workflow';
noteableType: NoteableType;
content: string;
parentNoteId: string | null;
}) =>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { useIsAuthenticated } from '@/domains/auth/context/AuthProvider/hooks/useIsAuthenticated/useIsAuthenticated';
import { useQuery } from '@tanstack/react-query';
import { isString } from '@/common/utils/is-string/is-string';
import { notesQueryKey } from '@/pages/Entity/components/Notes/hooks/query-keys';
import { NoteableType } from '@/pages/Entity/components/Notes/types';

export const useNotesByNoteable = ({
noteableType,
noteableId = '',
}: {
noteableType: NoteableType;
noteableId?: string;
}) => {
const isAuthenticated = useIsAuthenticated();

return useQuery({
...notesQueryKey.byNoteable({ noteableType, noteableId }),
enabled: isAuthenticated && isString(noteableId) && !!noteableId.length,
staleTime: 100_000,
refetchInterval: 1_000_000,
});
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { createQueryKeys } from '@lukemorales/query-key-factory';

import { NoteableType } from '@/pages/Entity/components/Notes/types';
import { getNotesByNotable } from '@/pages/Entity/components/Notes/hooks/fetchers';

export const notesQueryKey = createQueryKeys('notes', {
byNoteable: ({
noteableType,
noteableId,
}: {
noteableType: NoteableType;
noteableId: string;
}) => ({
queryKey: [{ noteableType, noteableId }],
queryFn: () => getNotesByNotable({ noteableType, noteableId }),
}),
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { z } from 'zod';

const BasicNoteSchema = z.object({
id: z.string(),
entityId: z.string(),
entityType: z.enum(['Business', 'EndUser']),
noteableId: z.string(),
noteableType: z.enum(['Report', 'Alert', 'Workflow']),
content: z.string(),
fileIds: z.array(z.string()),
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
});

export const NoteSchema = BasicNoteSchema.extend({
parentNote: z.union([BasicNoteSchema, z.null()]),
childrenNotes: z.array(BasicNoteSchema),
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { useCallback, useState } from 'react';
import { SubmitHandler } from 'react-hook-form';

import { useCreateNoteMutation } from '@/pages/Entity/components/Notes/hooks/mutations/useCreateNoteMutation/useCreateNoteMutation';
import { CreateNoteSchema } from '@/pages/Entity/components/Notes/hooks/create-note-schema';
import { CreateNoteSchema } from '@/pages/Entity/components/Notes/hooks/schemas/create-note-schema';

export const useNotesLogic = () => {
const [note, setNote] = useState('');
Expand All @@ -12,7 +12,7 @@ export const useNotesLogic = () => {
setNote(event.target.value);
}, []);

const { mutate: mutateCreateNote, isLoading: isSubmitting } = useCreateNoteMutation({});
const { mutate: mutateCreateNote, isLoading: isSubmitting } = useCreateNoteMutation();

const onSubmit: SubmitHandler<z.output<typeof CreateNoteSchema>> = data => {
mutateCreateNote(data);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type NoteableType = 'Report' | 'Alert' | 'Workflow';
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
import { useCurrentCaseQuery } from '@/pages/Entity/hooks/useCurrentCaseQuery/useCurrentCaseQuery';
import { useParams } from 'react-router-dom';
import { useNotesByNoteable } from '@/pages/Entity/components/Notes/hooks/queries/useNotesByNoteable/useNotesByNoteable';

export const useEntityLogic = () => {
const { entityId } = useParams();
const { data: notes } = useNotesByNoteable({ noteableId: entityId, noteableType: 'Workflow' });

const { data: workflow } = useCurrentCaseQuery();
const selectedEntity = workflow?.entity;

return {
selectedEntity,
workflow,
notes,
};
};
20 changes: 20 additions & 0 deletions services/workflows-service/src/note/dtos/get-by-noteable.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { IsNotEmpty, IsString } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { Noteable } from '@prisma/client';

export class GetByNoteableDto {
@ApiProperty({
required: true,
type: String,
})
@IsString()
@IsNotEmpty()
noteableId!: string;

@ApiProperty({
required: true,
enum: ['Workflow', 'Report', 'Alert'],
})
@IsString()
noteableType!: Noteable;
}
20 changes: 19 additions & 1 deletion services/workflows-service/src/note/note.controller.external.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { Param } from '@nestjs/common';
import * as common from '@nestjs/common';
import * as swagger from '@nestjs/swagger';

import type { TProjectId } from '@/types';
import { NoteModel } from '@/note/note.model';
import { NoteService } from '@/note/note.service';
import { CurrentProject } from '@/common/decorators/current-project.decorator';
import { CreateNoteDto } from './dtos/create-note.dto';
import { CurrentProject } from '@/common/decorators/current-project.decorator';
import { GetByNoteableDto } from '@/note/dtos/get-by-noteable.dto';

@swagger.ApiTags('Notes')
@swagger.ApiBearerAuth()
Expand All @@ -20,6 +22,22 @@ export class NoteControllerExternal {
return this.noteService.list(currentProjectId);
}

@common.Get('/:noteableType/:noteableId')
@swagger.ApiForbiddenResponse()
@swagger.ApiOkResponse({ type: Array<NoteModel> })
async getByNoteable(
@Param('noteableType') noteableType: GetByNoteableDto['noteableType'],
@Param('noteableId') noteableId: GetByNoteableDto['noteableId'],
@CurrentProject() currentProjectId: TProjectId,
) {
return this.noteService.list(currentProjectId, {
where: {
noteableId,
noteableType,
},
});
}

@common.Post()
@swagger.ApiForbiddenResponse()
@swagger.ApiCreatedResponse({ type: NoteModel })
Expand Down
8 changes: 5 additions & 3 deletions services/workflows-service/src/note/note.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class NoteRepository {
transaction: PrismaTransaction | PrismaClient = this.prismaService,
) {
return transaction.note.findMany({
...((args || defaultArgs) as Prisma.NoteFindManyArgs),
select: { ...(args?.select || defaultArgs.select) } as Prisma.NoteFindManyArgs['select'],
where: { ...(args?.where || {}), deletedAt: null, projectId },
});
}
Expand All @@ -55,7 +55,9 @@ export class NoteRepository {
transaction: PrismaTransaction | PrismaClient = this.prismaService,
) {
return transaction.note.findFirstOrThrow({
...((args || defaultArgs) as Prisma.NoteFindFirstOrThrowArgs),
select: {
...(args?.select || defaultArgs.select),
} as Prisma.NoteFindFirstOrThrowArgs['select'],
where: { id, deletedAt: null, projectId },
});
}
Expand All @@ -65,7 +67,7 @@ export class NoteRepository {
args?: Prisma.SelectSubset<T, Omit<Prisma.NoteFindManyArgs, 'where'>>,
) {
return this.prismaService.note.findMany({
...((args || defaultArgs) as Prisma.NoteFindManyArgs),
select: { ...(args?.select || defaultArgs.select) } as Prisma.NoteFindManyArgs['select'],
where: { deletedAt: null, projectId },
});
}
Expand Down

0 comments on commit f6f5fea

Please sign in to comment.