Files
twenty/packages/twenty-front/src/modules/activities/utils/getActivityPreview.ts
T
Piyush 9c334b5f03 fixed: Links in note preview not visible #16043 (#16267)
This PR fixes an issue where links added inside a note were not
appearing in the preview shown under Company -> Notes. The link would
only appear after opening the note, which led to inconsistent behavior.

Issue:
Blocknote represents text and links using different node types:
1. { "type": "text", "text": "Welcome to this demo!" }
2. {
  "type": "link",
  "content": { "type": "text", "text": "Example" },
  "href": "https://example.com"
}


The existing preview function only handled plain text nodes and
completely ignored link nodes.
As a result:
- Links did not appear in the preview
- Links appeared only inside the full note view


Steps to Reproduce:
- Add a link inside a note
- Go to Company / People and view the note preview -> the link is
missing
- Open the note -> the link appears correctly


How I fixed it:
- A new recursive text extraction function (extractText) was added to
correctly read.
- Text nodes
- Link nodes (including inner content and the href)
- Nested child content
- Link previews now appear in the following format:
DisplayText (https://example.com)



Edit : closes https://github.com/twentyhq/twenty/issues/16043

---------

Co-authored-by: Etienne <45695613+etiennejouan@users.noreply.github.com>
2025-12-03 19:23:04 +01:00

58 lines
1.3 KiB
TypeScript

// TODO: merge with getFirstNonEmptyLineOfRichText (and one duplicate I saw and also added a note on)
import { isArray, isNonEmptyString } from '@sniptt/guards';
interface BaseNode {
type: string;
content?: RichTextNode[];
[key: string]: unknown;
}
interface TextNode extends BaseNode {
type: 'text';
text: string;
}
interface LinkNode extends BaseNode {
type: 'link';
href?: string;
content?: RichTextNode[];
}
type RichTextNode = TextNode | LinkNode | BaseNode;
const isTextNode = (node: RichTextNode): node is TextNode =>
node.type === 'text';
const isLinkNode = (node: RichTextNode): node is LinkNode =>
node.type === 'link';
export const getActivityPreview = (activityBody: string | null): string => {
const noteBody: RichTextNode[] = activityBody ? JSON.parse(activityBody) : [];
const extractText = (node: RichTextNode | undefined | null): string => {
if (!node) return '';
if (isTextNode(node)) {
return node.text ?? '';
}
if (isLinkNode(node)) {
return node.content?.map(extractText).join(' ') ?? '';
}
if (isArray(node.content)) {
return node.content.map(extractText).join(' ');
}
return '';
};
return noteBody.length
? noteBody
.map((node) => extractText(node))
.filter(isNonEmptyString)
.join('\n')
: '';
};