Skip to content

Commit 0343fb6

Browse files
authored
Bulk edit fix rich text visualization [] (#10044)
* fix * dependencies * add tests
1 parent 8d6ee3b commit 0343fb6

4 files changed

Lines changed: 203 additions & 9 deletions

File tree

apps/bulk-edit/package-lock.json

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

apps/bulk-edit/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"@contentful/f36-tokens": "4.2.0",
1010
"@contentful/field-editor-json": "^3.3.38",
1111
"@contentful/react-apps-toolkit": "1.2.16",
12+
"@contentful/rich-text-html-renderer": "^17.1.0",
1213
"@phosphor-icons/react": "^2.1.10",
1314
"contentful-management": "^11.52.0",
1415
"emotion": "10.0.27",

apps/bulk-edit/src/locations/Page/utils/entryUtils.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { documentToHtmlString } from '@contentful/rich-text-html-renderer';
2+
import { Document } from '@contentful/rich-text-types';
13
import { Entry, ContentTypeField, Status, Fields } from '../types';
24
import { ContentTypeProps } from 'contentful-management';
35

@@ -67,6 +69,10 @@ export const renderFieldValue = (field: ContentTypeField, value: unknown): strin
6769
return `1 reference field`;
6870
}
6971

72+
if (field.type === 'RichText' && typeof value === 'object' && value !== null) {
73+
return truncate(documentToHtmlString(value as Document));
74+
}
75+
7076
if (typeof value === 'object' && value !== null) {
7177
return '';
7278
}

apps/bulk-edit/test/locations/Page/entryUtils.test.tsx

Lines changed: 152 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
import { describe, it, expect } from 'vitest';
2-
import {
3-
getEntryFieldValue,
4-
renderFieldValue,
5-
getEntryTitle,
6-
getStatus,
7-
isCheckboxAllowed,
8-
} from '../../../src/locations/Page/utils/entryUtils';
9-
import { Entry, ContentTypeField } from '../../../src/locations/Page/types';
10-
import { ContentTypeProps } from 'contentful-management';
2+
import { getEntryFieldValue, renderFieldValue } from '../../../src/locations/Page/utils/entryUtils';
3+
import { ContentTypeField } from '../../../src/locations/Page/types';
114

125
describe('entryUtils', () => {
136
describe('getEntryFieldValue', () => {
@@ -105,4 +98,154 @@ describe('entryUtils', () => {
10598
expect(result).toBe('empty field');
10699
});
107100
});
101+
102+
describe('renderFieldValue', () => {
103+
it('returns truncated string for Symbol field with string value', () => {
104+
const field = { id: 'testField', locale: 'en-US', type: 'Symbol' } as ContentTypeField;
105+
const result = renderFieldValue(field, 'This is a long string that should be truncated');
106+
expect(result).toBe('This is a long strin ...');
107+
});
108+
109+
it('returns truncated string for Text field with string value', () => {
110+
const field = { id: 'testField', locale: 'en-US', type: 'Text' } as ContentTypeField;
111+
const result = renderFieldValue(field, 'This is a text field with long content');
112+
expect(result).toBe('This is a text field ...');
113+
});
114+
115+
it('returns truncated string for Integer field with number value', () => {
116+
const field = { id: 'testField', locale: 'en-US', type: 'Integer' } as ContentTypeField;
117+
const result = renderFieldValue(field, 42);
118+
expect(result).toBe('42');
119+
});
120+
121+
it('returns truncated string for Number field with decimal value', () => {
122+
const field = { id: 'testField', locale: 'en-US', type: 'Number' } as ContentTypeField;
123+
const result = renderFieldValue(field, 3.14159);
124+
expect(result).toBe('3.14159');
125+
});
126+
127+
it('returns truncated string for Date field with date value', () => {
128+
const field = { id: 'testField', locale: 'en-US', type: 'Date' } as ContentTypeField;
129+
const dateValue = '2023-12-25';
130+
const result = renderFieldValue(field, dateValue);
131+
expect(result).toBe('2023-12-25');
132+
});
133+
134+
it('returns location string for Location field', () => {
135+
const field = { id: 'testField', locale: 'en-US', type: 'Location' } as ContentTypeField;
136+
const locationValue = { lat: 40.7128, lon: -74.006 };
137+
const result = renderFieldValue(field, locationValue);
138+
expect(result).toBe('Lat: 40.7128, Lon: - ...');
139+
});
140+
141+
it('returns "true" for Boolean field with true value', () => {
142+
const field = { id: 'testField', locale: 'en-US', type: 'Boolean' } as ContentTypeField;
143+
const result = renderFieldValue(field, true);
144+
expect(result).toBe('true');
145+
});
146+
147+
it('returns truncated JSON string for Object field', () => {
148+
const field = { id: 'testField', locale: 'en-US', type: 'Object' } as ContentTypeField;
149+
const objectValue = { name: 'John', age: 30, city: 'New York' };
150+
const result = renderFieldValue(field, objectValue);
151+
expect(result).toBe('{"name":"John","age" ...');
152+
});
153+
154+
it('returns the truncated html string of a rich text field', () => {
155+
const field = { id: 'testField', locale: 'en-US', type: 'RichText' } as ContentTypeField;
156+
const richTextValue = {
157+
nodeType: 'document',
158+
data: {},
159+
content: [
160+
{
161+
nodeType: 'paragraph',
162+
data: {},
163+
content: [
164+
{
165+
nodeType: 'text',
166+
value: 'this is a test value',
167+
marks: [],
168+
data: {},
169+
},
170+
],
171+
},
172+
],
173+
};
174+
175+
const result = renderFieldValue(field, richTextValue);
176+
177+
expect(result).toBe('<p>this is a test va ...');
178+
});
179+
180+
it('returns "1 asset" for Link field with Asset reference', () => {
181+
const field = { id: 'testField', locale: 'en-US', type: 'Link' } as ContentTypeField;
182+
const linkValue = { sys: { linkType: 'Asset' } };
183+
const result = renderFieldValue(field, linkValue);
184+
expect(result).toBe('1 asset');
185+
});
186+
187+
it('returns "1 reference field" for Link field with Entry reference', () => {
188+
const field = { id: 'testField', locale: 'en-US', type: 'Link' } as ContentTypeField;
189+
const linkValue = { sys: { linkType: 'Entry' } };
190+
const result = renderFieldValue(field, linkValue);
191+
expect(result).toBe('1 reference field');
192+
});
193+
194+
it('returns "1 reference field" for Array field with single Entry reference', () => {
195+
const field = { id: 'testField', locale: 'en-US', type: 'Array' } as ContentTypeField;
196+
const arrayValue = [{ sys: { linkType: 'Entry' } }];
197+
const result = renderFieldValue(field, arrayValue);
198+
expect(result).toBe('1 reference field');
199+
});
200+
201+
it('returns "2 reference fields" for Array field with multiple Entry references', () => {
202+
const field = { id: 'testField', locale: 'en-US', type: 'Array' } as ContentTypeField;
203+
const arrayValue = [{ sys: { linkType: 'Entry' } }, { sys: { linkType: 'Entry' } }];
204+
const result = renderFieldValue(field, arrayValue);
205+
expect(result).toBe('2 reference fields');
206+
});
207+
208+
it('returns "1 asset" for Array field with single Asset reference', () => {
209+
const field = { id: 'testField', locale: 'en-US', type: 'Array' } as ContentTypeField;
210+
const arrayValue = [{ sys: { linkType: 'Asset' } }];
211+
const result = renderFieldValue(field, arrayValue);
212+
expect(result).toBe('1 asset');
213+
});
214+
215+
it('returns "3 assets" for Array field with multiple Asset references', () => {
216+
const field = { id: 'testField', locale: 'en-US', type: 'Array' } as ContentTypeField;
217+
const arrayValue = [
218+
{ sys: { linkType: 'Asset' } },
219+
{ sys: { linkType: 'Asset' } },
220+
{ sys: { linkType: 'Asset' } },
221+
];
222+
const result = renderFieldValue(field, arrayValue);
223+
expect(result).toBe('3 assets');
224+
});
225+
226+
it('returns truncated string for Array field with string values', () => {
227+
const field = { id: 'testField', locale: 'en-US', type: 'Array' } as ContentTypeField;
228+
const arrayValue = ['apple', 'banana', 'cherry'];
229+
const result = renderFieldValue(field, arrayValue);
230+
expect(result).toBe('apple, banana, cherr ...');
231+
});
232+
233+
it('returns "-" for undefined value', () => {
234+
const field = { id: 'testField', locale: 'en-US', type: 'Symbol' } as ContentTypeField;
235+
const result = renderFieldValue(field, undefined);
236+
expect(result).toBe('-');
237+
});
238+
239+
it('returns "-" for null value', () => {
240+
const field = { id: 'testField', locale: 'en-US', type: 'Symbol' } as ContentTypeField;
241+
const result = renderFieldValue(field, null);
242+
expect(result).toBe('-');
243+
});
244+
245+
it('returns truncated string for empty array', () => {
246+
const field = { id: 'testField', locale: 'en-US', type: 'Array' } as ContentTypeField;
247+
const result = renderFieldValue(field, []);
248+
expect(result).toBe('');
249+
});
250+
});
108251
});

0 commit comments

Comments
 (0)