From 40af5ec57bc57cff2fe4eafe3640caae361cb1e5 Mon Sep 17 00:00:00 2001 From: Mathieu Date: Fri, 2 Feb 2024 15:26:59 +0100 Subject: [PATCH] feat(app): add grouped messages --- .../app/src/front/components/grid/LogCell.tsx | 22 ++++- packages/app/src/front/stores/messageStore.ts | 30 ++++++- packages/app/src/front/utils/message.spec.ts | 88 +++++++++++++++++++ packages/app/src/front/utils/message.ts | 19 ++++ 4 files changed, 154 insertions(+), 5 deletions(-) create mode 100644 packages/app/src/front/utils/message.spec.ts create mode 100644 packages/app/src/front/utils/message.ts diff --git a/packages/app/src/front/components/grid/LogCell.tsx b/packages/app/src/front/components/grid/LogCell.tsx index 42e8872..5fb8087 100644 --- a/packages/app/src/front/components/grid/LogCell.tsx +++ b/packages/app/src/front/components/grid/LogCell.tsx @@ -1,9 +1,11 @@ import { FsdtLogMessageContent } from '@fullstack-devtool/core' import styled from '@emotion/styled' import { ObjectView } from '../ObjectView' +import { StoredMessage } from '../../stores/messageStore' type LogCellProps = { value: FsdtLogMessageContent + data: StoredMessage } const StyledLogCell = styled.div` @@ -13,8 +15,24 @@ const StyledLogCell = styled.div` * { font-family: ${(props) => props.theme.fontFamily.secondary}; } + display: flex; + align-items: center; ` -export const LogCell = ({ value }: LogCellProps) => { - return {typeof value === 'object' ? : value} +const Quantity = styled.span` + margin-left: 8px; + background-color: ${(props) => props.theme.colors.primary}; + color: white; + padding: 2px 4px; + border-radius: 400px; + font-size: 12px; +` + +export const LogCell = ({ value, data }: LogCellProps) => { + return ( + + {typeof value === 'object' ? : value} + {data.quantity > 1 && {data.quantity}} + + ) } diff --git a/packages/app/src/front/stores/messageStore.ts b/packages/app/src/front/stores/messageStore.ts index 306ba62..91708ce 100644 --- a/packages/app/src/front/stores/messageStore.ts +++ b/packages/app/src/front/stores/messageStore.ts @@ -1,8 +1,13 @@ import { FsdtLogMessageContent, FsdtServerMessage } from '@fullstack-devtool/core' import { create } from 'zustand' +import { groupMessagesWithTheSameContent } from '../utils/message' + +export type StoredMessage = FsdtServerMessage & { + quantity: number +} interface MessageState { - messages: FsdtServerMessage[] + messages: StoredMessage[] sources: string[] tags: string[] addMessage: (message: FsdtServerMessage) => void @@ -16,6 +21,18 @@ export const useMessageStore = create((set) => ({ tags: [], addMessage: (message) => set((state) => { + // Group messages with the same content + const lastMessage = state.messages[state.messages.length - 1] + if ( + lastMessage && + lastMessage.source === message.source && + lastMessage.data.content === message.data.content && + lastMessage.data.tag === message.data.tag + ) { + lastMessage.quantity++ + return { messages: [...state.messages] } + } + // Add new message const newSources = [...state.sources] const newTags = [...state.tags] if (!newSources.includes(message.source)) { @@ -24,7 +41,7 @@ export const useMessageStore = create((set) => ({ if (!newTags.includes(message.data.tag) && message.data.tag) { newTags.push(message.data.tag) } - return { messages: [...state.messages, message], sources: newSources, tags: newTags } + return { messages: [...state.messages, { ...message, quantity: 1 }], sources: newSources, tags: newTags } }), addMessages: (messages) => set((state) => { @@ -38,7 +55,14 @@ export const useMessageStore = create((set) => ({ newTags.push(message.data.tag) } }) - return { messages: [...state.messages, ...messages], sources: newSources, tags: newTags } + return { + messages: groupMessagesWithTheSameContent([ + ...state.messages, + ...messages.map((mess) => ({ ...mess, quantity: 1 })), + ]), + sources: newSources, + tags: newTags, + } }), clearMessages: () => set({ messages: [] }), })) diff --git a/packages/app/src/front/utils/message.spec.ts b/packages/app/src/front/utils/message.spec.ts new file mode 100644 index 0000000..34c131b --- /dev/null +++ b/packages/app/src/front/utils/message.spec.ts @@ -0,0 +1,88 @@ +import { EventType, LogLevel } from '@fullstack-devtool/core' +import { StoredMessage } from '../stores/messageStore' +import { groupMessagesWithTheSameContent } from './message' + +describe('message', () => { + describe('groupMessagesWithTheSameContent', () => { + it('should group messages with the same content', () => { + const allMessages: StoredMessage[] = [ + { + id: 1, + source: 'source1', + type: EventType.LOG, + data: { + content: 'content1', + tag: 'tag1', + timestamp: '1', + level: LogLevel.LOG, + }, + quantity: 1, + }, + { + id: 2, + source: 'source1', + type: EventType.LOG, + data: { + content: 'content1', + tag: 'tag1', + timestamp: '2', + level: LogLevel.LOG, + }, + quantity: 1, + }, + { + id: 3, + source: 'source1', + type: EventType.LOG, + data: { + content: 'content2', + tag: 'tag1', + timestamp: '3', + level: LogLevel.LOG, + }, + quantity: 1, + }, + { + id: 4, + source: 'source1', + type: EventType.LOG, + data: { + content: 'content2', + tag: 'tag1', + timestamp: '4', + level: LogLevel.LOG, + }, + quantity: 1, + }, + ] + const groupedMessages: StoredMessage[] = [ + { + id: 1, + source: 'source1', + type: EventType.LOG, + data: { + content: 'content1', + tag: 'tag1', + timestamp: '1', + level: LogLevel.LOG, + }, + quantity: 2, + }, + { + id: 3, + source: 'source1', + type: EventType.LOG, + data: { + content: 'content2', + tag: 'tag1', + timestamp: '3', + level: LogLevel.LOG, + }, + quantity: 2, + }, + ] + + expect(groupMessagesWithTheSameContent(allMessages)).toEqual(groupedMessages) + }) + }) +}) diff --git a/packages/app/src/front/utils/message.ts b/packages/app/src/front/utils/message.ts new file mode 100644 index 0000000..34335bb --- /dev/null +++ b/packages/app/src/front/utils/message.ts @@ -0,0 +1,19 @@ +import { StoredMessage } from '../stores/messageStore' + +export const groupMessagesWithTheSameContent = (messages: StoredMessage[]) => { + const groupedMessages: StoredMessage[] = [] + messages.forEach((message) => { + const lastMessage = groupedMessages[groupedMessages.length - 1] + if ( + lastMessage && + lastMessage.source === message.source && + lastMessage.data.content === message.data.content && + lastMessage.data.tag === message.data.tag + ) { + lastMessage.quantity++ + } else { + groupedMessages.push({ ...message, quantity: 1 }) + } + }) + return groupedMessages +}