Skip to content

Commit cccb0b0

Browse files
feat(taxonomy): added view/create/updated taxonomy field support (#3716)
* feat(taxonomy): added create/updated taxonomy support * feat(taxonomy): fixed tests and lint errors
1 parent 5a117ae commit cccb0b0

File tree

4 files changed

+92
-20
lines changed

4 files changed

+92
-20
lines changed

src/api/Metadata.js

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import uniqueId from 'lodash/uniqueId';
99
import isEmpty from 'lodash/isEmpty';
1010
import { getBadItemError, getBadPermissionsError, isUserCorrectableError } from '../utils/error';
1111
import { getTypedFileId } from '../utils/file';
12-
import { handleOnAbort } from './utils';
12+
import { handleOnAbort, formatMetadataFieldValue } from './utils';
1313
import File from './File';
1414
import {
1515
HEADER_CONTENT_TYPE,
@@ -226,14 +226,17 @@ class Metadata extends File {
226226
* Gets metadata instances for a Box file
227227
*
228228
* @param {string} id - file id
229+
* @param {boolean} isMetadataRedesign - feature flag
229230
* @return {Object} array of metadata instances
230231
*/
231-
async getInstances(id: string): Promise<Array<MetadataInstanceV2>> {
232+
async getInstances(id: string, isMetadataRedesign: boolean = false): Promise<Array<MetadataInstanceV2>> {
232233
this.errorCode = ERROR_CODE_FETCH_METADATA;
234+
const baseUrl = this.getMetadataUrl(id);
235+
const url = isMetadataRedesign ? `${baseUrl}?view=hydrated` : baseUrl;
233236
let instances = {};
234237
try {
235238
instances = await this.xhr.get({
236-
url: this.getMetadataUrl(id),
239+
url,
237240
id: getTypedFileId(id),
238241
});
239242
} catch (e) {
@@ -377,9 +380,11 @@ class Metadata extends File {
377380
// Get Metadata Fields for Instances created from predefined template
378381
const templateFields = template.fields || [];
379382
templateFields.forEach(field => {
383+
const value = formatMetadataFieldValue(field, instance[field.key]);
384+
380385
fields.push({
381386
...field,
382-
value: instance[field.key],
387+
value,
383388
});
384389
});
385390
} else {
@@ -501,7 +506,7 @@ class Metadata extends File {
501506
try {
502507
const customPropertiesTemplate: MetadataTemplate = this.getCustomPropertiesTemplate();
503508
const [instances, globalTemplates, enterpriseTemplates] = await Promise.all([
504-
this.getInstances(id),
509+
this.getInstances(id, isMetadataRedesign),
505510
this.getTemplates(id, METADATA_SCOPE_GLOBAL),
506511
hasMetadataFeature ? this.getTemplates(id, METADATA_SCOPE_ENTERPRISE) : Promise.resolve([]),
507512
]);
@@ -887,11 +892,24 @@ class Metadata extends File {
887892
try {
888893
const fieldsValues = template.fields.reduce((acc, obj) => {
889894
let { value } = obj;
895+
890896
// API does not accept string for float type
891-
if (obj.type === 'float' && value) value = parseFloat(obj.value);
897+
if (obj.type === 'float' && value) {
898+
value = parseFloat(obj.value);
899+
}
900+
892901
// API does not accept empty string for enum type
893-
if (obj.type === 'enum' && value && value.length === 0) value = undefined;
902+
if (obj.type === 'enum' && value && value.length === 0) {
903+
value = undefined;
904+
}
905+
906+
// API expects values as an array of strings
907+
if (obj.type === 'taxonomy' && value && Array.isArray(value)) {
908+
value = value.map(option => option.value);
909+
}
910+
894911
acc[obj.key] = value;
912+
895913
return acc;
896914
}, {});
897915

src/api/__tests__/Metadata.test.js

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { handleOnAbort } from '../utils';
2525
let metadata: Metadata;
2626

2727
jest.mock('../utils', () => ({
28+
...jest.requireActual('../utils'),
2829
handleOnAbort: jest.fn(),
2930
}));
3031

@@ -443,6 +444,19 @@ describe('api/Metadata', () => {
443444
id: 'file_id',
444445
});
445446
});
447+
test('should apply hydrated query string param for isMetadataRedesign', async () => {
448+
metadata.getMetadataUrl = jest.fn().mockReturnValueOnce('metadata_url');
449+
metadata.xhr.get = jest.fn().mockReturnValueOnce({
450+
data: {
451+
entries: [],
452+
},
453+
});
454+
await metadata.getInstances('id', true);
455+
expect(metadata.xhr.get).toHaveBeenCalledWith({
456+
url: 'metadata_url?view=hydrated',
457+
id: 'file_id',
458+
});
459+
});
446460
});
447461

448462
describe('getUserAddableTemplates()', () => {
@@ -810,7 +824,7 @@ describe('api/Metadata', () => {
810824
expect(metadata.isDestroyed).toHaveBeenCalled();
811825
expect(metadata.getCache).toHaveBeenCalled();
812826
expect(metadata.getMetadataCacheKey).toHaveBeenCalledWith(file.id);
813-
expect(metadata.getInstances).toHaveBeenCalledWith(file.id);
827+
expect(metadata.getInstances).toHaveBeenCalledWith(file.id, false);
814828
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'global');
815829
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'enterprise');
816830
expect(metadata.extractClassification).toBeCalledWith('id', 'instances');
@@ -865,7 +879,7 @@ describe('api/Metadata', () => {
865879
expect(metadata.isDestroyed).toHaveBeenCalled();
866880
expect(metadata.getCache).toHaveBeenCalled();
867881
expect(metadata.getMetadataCacheKey).toHaveBeenCalledWith(file.id);
868-
expect(metadata.getInstances).toHaveBeenCalledWith(file.id);
882+
expect(metadata.getInstances).toHaveBeenCalledWith(file.id, true);
869883
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'global');
870884
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'enterprise');
871885
expect(metadata.extractClassification).toBeCalledWith('id', 'instances');
@@ -922,7 +936,7 @@ describe('api/Metadata', () => {
922936
expect(metadata.isDestroyed).toHaveBeenCalled();
923937
expect(metadata.getCache).toHaveBeenCalled();
924938
expect(metadata.getMetadataCacheKey).toHaveBeenCalledWith(file.id);
925-
expect(metadata.getInstances).toHaveBeenCalledWith(file.id);
939+
expect(metadata.getInstances).toHaveBeenCalledWith(file.id, false);
926940
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'global');
927941
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'enterprise');
928942
expect(metadata.extractClassification).toBeCalledWith('id', 'instances');
@@ -980,7 +994,7 @@ describe('api/Metadata', () => {
980994
expect(metadata.isDestroyed).toHaveBeenCalled();
981995
expect(metadata.getCache).toHaveBeenCalled();
982996
expect(metadata.getMetadataCacheKey).toHaveBeenCalledWith(file.id);
983-
expect(metadata.getInstances).toHaveBeenCalledWith(file.id);
997+
expect(metadata.getInstances).toHaveBeenCalledWith(file.id, false);
984998
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'global');
985999
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'enterprise');
9861000
expect(metadata.extractClassification).toBeCalledWith('id', 'instances');
@@ -1037,7 +1051,7 @@ describe('api/Metadata', () => {
10371051
expect(metadata.isDestroyed).toHaveBeenCalled();
10381052
expect(metadata.getCache).toHaveBeenCalled();
10391053
expect(metadata.getMetadataCacheKey).toHaveBeenCalledWith(file.id);
1040-
expect(metadata.getInstances).toHaveBeenCalledWith(file.id);
1054+
expect(metadata.getInstances).toHaveBeenCalledWith(file.id, false);
10411055
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'global');
10421056
expect(metadata.getTemplates).not.toHaveBeenCalledWith(file.id, 'enterprise');
10431057
expect(metadata.extractClassification).toBeCalledWith('id', 'instances');
@@ -1092,7 +1106,7 @@ describe('api/Metadata', () => {
10921106
expect(metadata.isDestroyed).not.toHaveBeenCalled();
10931107
expect(metadata.getCache).toHaveBeenCalled();
10941108
expect(metadata.getMetadataCacheKey).toHaveBeenCalledWith(file.id);
1095-
expect(metadata.getInstances).toHaveBeenCalledWith(file.id);
1109+
expect(metadata.getInstances).toHaveBeenCalledWith(file.id, false);
10961110
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'global');
10971111
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'enterprise');
10981112
expect(metadata.getEditors).not.toHaveBeenCalled();
@@ -1132,7 +1146,7 @@ describe('api/Metadata', () => {
11321146
expect(metadata.isDestroyed).toHaveBeenCalled();
11331147
expect(metadata.getCache).toHaveBeenCalled();
11341148
expect(metadata.getMetadataCacheKey).toHaveBeenCalledWith(file.id);
1135-
expect(metadata.getInstances).toHaveBeenCalledWith(file.id);
1149+
expect(metadata.getInstances).toHaveBeenCalledWith(file.id, false);
11361150
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'global');
11371151
expect(metadata.getTemplates).toHaveBeenCalledWith(file.id, 'enterprise');
11381152
expect(metadata.extractClassification).toBeCalledWith('id', 'instances');

src/api/__tests__/utils.test.js

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import Xhr from '../../utils/Xhr';
22
import { getAbortError } from '../../utils/error';
3-
import { formatComment, handleOnAbort } from '../utils';
3+
import { formatComment, formatMetadataFieldValue, handleOnAbort } from '../utils';
44
import { threadedComments, threadedCommentsFormatted } from '../fixtures';
5+
import { FIELD_TYPE_STRING, FIELD_TYPE_TAXONOMY } from '../../features/metadata-instance-fields/constants';
56

67
jest.mock('../../utils/Xhr', () => {
78
return jest.fn().mockImplementation(() => ({
@@ -26,4 +27,32 @@ describe('api/utils', () => {
2627
expect(xhr.abort).toHaveBeenCalled();
2728
});
2829
});
30+
31+
describe('formatMetadataFieldValue()', () => {
32+
test('should format string field value', async () => {
33+
const stringField = {
34+
displayName: 'State',
35+
id: '1',
36+
key: 'stateField',
37+
type: FIELD_TYPE_STRING,
38+
};
39+
const value = 'California';
40+
41+
expect(formatMetadataFieldValue(stringField, value)).toEqual(value);
42+
});
43+
44+
test('should format taxonomy field value', async () => {
45+
const taxonomyField = {
46+
displayName: 'State',
47+
id: '1',
48+
key: 'stateField',
49+
type: FIELD_TYPE_TAXONOMY,
50+
};
51+
const id = '123-456';
52+
const displayName = 'California';
53+
const expectedValue = [{ value: id, displayValue: displayName }];
54+
55+
expect(formatMetadataFieldValue(taxonomyField, [{ id, displayName }])).toEqual(expectedValue);
56+
});
57+
});
2958
});

src/api/utils.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,16 @@
77
import type Xhr from '../utils/Xhr';
88
import type { Comment } from '../common/types/feed';
99
import { getAbortError } from '../utils/error';
10+
import type { MetadataTemplateField, MetadataFieldValue } from '../common/types/metadata';
11+
import { FIELD_TYPE_TAXONOMY } from '../features/metadata-instance-fields/constants';
1012

1113
/**
1214
* Formats comment data (including replies) for use in components.
1315
*
1416
* @param {Comment} comment - An individual comment entry from the API
1517
* @return {Comment} Updated comment
1618
*/
17-
export const formatComment = (comment: Comment): Comment => {
19+
const formatComment = (comment: Comment): Comment => {
1820
const formattedComment = {
1921
...comment,
2022
tagged_message: comment.message,
@@ -27,12 +29,21 @@ export const formatComment = (comment: Comment): Comment => {
2729
return formattedComment;
2830
};
2931

30-
export const handleOnAbort = (xhr: Xhr) => {
32+
const formatMetadataFieldValue = (field: MetadataTemplateField, value: MetadataFieldValue): MetadataFieldValue => {
33+
if (field.type === FIELD_TYPE_TAXONOMY && Array.isArray(value)) {
34+
return value.map((option: { id: string, displayName: string }) => ({
35+
value: option.id,
36+
displayValue: option.displayName,
37+
}));
38+
}
39+
40+
return value;
41+
};
42+
43+
const handleOnAbort = (xhr: Xhr) => {
3144
xhr.abort();
3245

3346
throw getAbortError();
3447
};
3548

36-
export default {
37-
formatComment,
38-
};
49+
export { formatComment, formatMetadataFieldValue, handleOnAbort };

0 commit comments

Comments
 (0)