box-ui-elements 24.0.0-beta.4 → 24.0.0-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/explorer.css +1 -1
- package/dist/explorer.js +1 -1
- package/dist/openwith.js +1 -1
- package/dist/picker.js +1 -1
- package/dist/preview.js +1 -1
- package/dist/sharing.js +1 -1
- package/dist/sidebar.js +1 -1
- package/dist/uploader.js +1 -1
- package/es/api/Metadata.js +98 -13
- package/es/api/Metadata.js.flow +110 -12
- package/es/api/Metadata.js.map +1 -1
- package/es/elements/common/messages.js +16 -0
- package/es/elements/common/messages.js.flow +25 -0
- package/es/elements/common/messages.js.map +1 -1
- package/es/elements/content-explorer/Content.js +5 -2
- package/es/elements/content-explorer/Content.js.map +1 -1
- package/es/elements/content-explorer/ContentExplorer.js +31 -6
- package/es/elements/content-explorer/ContentExplorer.js.map +1 -1
- package/es/elements/content-explorer/MetadataQueryAPIHelper.js +164 -10
- package/es/elements/content-explorer/MetadataQueryAPIHelper.js.map +1 -1
- package/es/elements/content-explorer/MetadataQueryBuilder.js +115 -0
- package/es/elements/content-explorer/MetadataQueryBuilder.js.map +1 -0
- package/es/elements/content-explorer/MetadataSidePanel.js +40 -14
- package/es/elements/content-explorer/MetadataSidePanel.js.map +1 -1
- package/es/elements/content-explorer/MetadataViewContainer.js +133 -36
- package/es/elements/content-explorer/MetadataViewContainer.js.map +1 -1
- package/es/elements/content-explorer/stories/MetadataView.stories.js +3 -25
- package/es/elements/content-explorer/stories/MetadataView.stories.js.map +1 -1
- package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js +65 -29
- package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js.map +1 -1
- package/es/elements/content-explorer/utils.js +140 -12
- package/es/elements/content-explorer/utils.js.map +1 -1
- package/es/src/elements/common/__mocks__/mockMetadata.d.ts +8 -24
- package/es/src/elements/content-explorer/Content.d.ts +4 -3
- package/es/src/elements/content-explorer/ContentExplorer.d.ts +19 -6
- package/es/src/elements/content-explorer/MetadataQueryAPIHelper.d.ts +22 -3
- package/es/src/elements/content-explorer/MetadataQueryBuilder.d.ts +27 -0
- package/es/src/elements/content-explorer/MetadataSidePanel.d.ts +6 -3
- package/es/src/elements/content-explorer/MetadataViewContainer.d.ts +10 -4
- package/es/src/elements/content-explorer/__tests__/MetadataQueryBuilder.test.d.ts +1 -0
- package/es/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.d.ts +1 -0
- package/es/src/elements/content-explorer/utils.d.ts +9 -3
- package/i18n/bn-IN.js +4 -0
- package/i18n/bn-IN.properties +12 -0
- package/i18n/da-DK.js +4 -0
- package/i18n/da-DK.properties +12 -0
- package/i18n/de-DE.js +5 -1
- package/i18n/de-DE.properties +12 -0
- package/i18n/en-AU.js +4 -0
- package/i18n/en-AU.properties +12 -0
- package/i18n/en-CA.js +4 -0
- package/i18n/en-CA.properties +12 -0
- package/i18n/en-GB.js +4 -0
- package/i18n/en-GB.properties +12 -0
- package/i18n/en-US.js +4 -0
- package/i18n/en-US.properties +8 -0
- package/i18n/en-x-pseudo.js +4 -0
- package/i18n/es-419.js +5 -1
- package/i18n/es-419.properties +12 -0
- package/i18n/es-ES.js +5 -1
- package/i18n/es-ES.properties +12 -0
- package/i18n/fi-FI.js +4 -0
- package/i18n/fi-FI.properties +12 -0
- package/i18n/fr-CA.js +4 -0
- package/i18n/fr-CA.properties +12 -0
- package/i18n/fr-FR.js +4 -0
- package/i18n/fr-FR.properties +12 -0
- package/i18n/hi-IN.js +4 -0
- package/i18n/hi-IN.properties +12 -0
- package/i18n/it-IT.js +4 -0
- package/i18n/it-IT.properties +12 -0
- package/i18n/ja-JP.js +6 -2
- package/i18n/ja-JP.properties +14 -2
- package/i18n/ko-KR.js +4 -0
- package/i18n/ko-KR.properties +12 -0
- package/i18n/nb-NO.js +4 -0
- package/i18n/nb-NO.properties +12 -0
- package/i18n/nl-NL.js +4 -0
- package/i18n/nl-NL.properties +12 -0
- package/i18n/pl-PL.js +4 -0
- package/i18n/pl-PL.properties +12 -0
- package/i18n/pt-BR.js +4 -0
- package/i18n/pt-BR.properties +12 -0
- package/i18n/ru-RU.js +5 -1
- package/i18n/ru-RU.properties +12 -0
- package/i18n/sv-SE.js +4 -0
- package/i18n/sv-SE.properties +12 -0
- package/i18n/tr-TR.js +5 -1
- package/i18n/tr-TR.properties +12 -0
- package/i18n/zh-CN.js +4 -0
- package/i18n/zh-CN.properties +12 -0
- package/i18n/zh-TW.js +4 -0
- package/i18n/zh-TW.properties +12 -0
- package/package.json +3 -3
- package/src/api/Metadata.js +110 -12
- package/src/api/__tests__/Metadata.test.js +120 -0
- package/src/elements/common/__mocks__/mockMetadata.ts +7 -11
- package/src/elements/common/messages.js +25 -0
- package/src/elements/content-explorer/Content.tsx +9 -2
- package/src/elements/content-explorer/ContentExplorer.tsx +71 -17
- package/src/elements/content-explorer/MetadataQueryAPIHelper.ts +199 -8
- package/src/elements/content-explorer/MetadataQueryBuilder.ts +159 -0
- package/src/elements/content-explorer/MetadataSidePanel.tsx +55 -14
- package/src/elements/content-explorer/MetadataViewContainer.tsx +164 -29
- package/src/elements/content-explorer/__tests__/Content.test.tsx +1 -0
- package/src/elements/content-explorer/__tests__/ContentExplorer.test.tsx +38 -7
- package/src/elements/content-explorer/__tests__/MetadataQueryAPIHelper.test.ts +428 -12
- package/src/elements/content-explorer/__tests__/MetadataQueryBuilder.test.ts +419 -0
- package/src/elements/content-explorer/__tests__/MetadataSidePanel.test.tsx +145 -3
- package/src/elements/content-explorer/__tests__/MetadataViewContainer.test.tsx +413 -9
- package/src/elements/content-explorer/stories/MetadataView.stories.tsx +3 -21
- package/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx +56 -21
- package/src/elements/content-explorer/utils.ts +150 -13
|
@@ -1,12 +1,24 @@
|
|
|
1
|
-
import { useMemo } from 'react';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
import { useIntl } from 'react-intl';
|
|
3
|
+
import isNil from 'lodash/isNil';
|
|
4
|
+
import xor from 'lodash/xor';
|
|
3
5
|
|
|
4
|
-
import
|
|
6
|
+
import {
|
|
7
|
+
MULTI_VALUE_DEFAULT_OPTION,
|
|
8
|
+
MULTI_VALUE_DEFAULT_VALUE,
|
|
9
|
+
type MetadataTemplate,
|
|
10
|
+
type MetadataFormFieldValue,
|
|
11
|
+
} from '@box/metadata-editor';
|
|
12
|
+
import type { MetadataFieldType } from '@box/metadata-view';
|
|
5
13
|
import type { Selection } from 'react-aria-components';
|
|
6
14
|
import type { BoxItem, Collection } from '../../common/types/core';
|
|
7
15
|
|
|
8
16
|
import messages from '../common/messages';
|
|
9
17
|
|
|
18
|
+
// Specific type for metadata field value in the item
|
|
19
|
+
// Note: Item doesn't have field value in metadata object if that field is not set, so the value will be undefined in this case
|
|
20
|
+
type ItemMetadataFieldValue = string | number | Array<string> | null | undefined;
|
|
21
|
+
|
|
10
22
|
// Get selected item text
|
|
11
23
|
export function useSelectedItemText(currentCollection: Collection, selectedItemIds: Selection): string {
|
|
12
24
|
const { formatMessage } = useIntl();
|
|
@@ -28,21 +40,146 @@ export function useSelectedItemText(currentCollection: Collection, selectedItemI
|
|
|
28
40
|
}, [currentCollection.items, formatMessage, selectedItemIds]);
|
|
29
41
|
}
|
|
30
42
|
|
|
43
|
+
// Check if the field value is empty.
|
|
44
|
+
// Note: 0 doesn't represent empty here because of float type field
|
|
45
|
+
export function isEmptyValue(value: ItemMetadataFieldValue) {
|
|
46
|
+
if (isNil(value)) {
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// date, string, enum
|
|
51
|
+
if (value === '') {
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// multiSelect
|
|
56
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// float
|
|
61
|
+
if (Number.isNaN(value)) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// Check if the field values are equal based on the field types
|
|
69
|
+
export function areFieldValuesEqual(value1: ItemMetadataFieldValue, value2: ItemMetadataFieldValue) {
|
|
70
|
+
if (isEmptyValue(value1) && isEmptyValue(value2)) {
|
|
71
|
+
return true;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Handle multiSelect arrays comparison
|
|
75
|
+
if (Array.isArray(value1) && Array.isArray(value2)) {
|
|
76
|
+
return xor(value1, value2).length === 0;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return value1 === value2;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Return default form value by field type
|
|
83
|
+
function getDefaultValueByFieldType(fieldType: MetadataFieldType) {
|
|
84
|
+
if (fieldType === 'date' || fieldType === 'enum' || fieldType === 'float' || fieldType === 'string') {
|
|
85
|
+
return '';
|
|
86
|
+
}
|
|
87
|
+
if (fieldType === 'multiSelect') {
|
|
88
|
+
return [];
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Set the field value in Metadata Form based on the field type
|
|
94
|
+
function getFieldValue(fieldType: MetadataFieldType, fieldValue: ItemMetadataFieldValue) {
|
|
95
|
+
if (isNil(fieldValue)) {
|
|
96
|
+
return getDefaultValueByFieldType(fieldType);
|
|
97
|
+
}
|
|
98
|
+
return fieldValue;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Check if the field value in Metadata Form is multi-values such as "Multiple values"
|
|
102
|
+
export function isMultiValuesField(fieldType: MetadataFieldType, fieldValue: MetadataFormFieldValue) {
|
|
103
|
+
if (fieldType === 'multiSelect') {
|
|
104
|
+
return Array.isArray(fieldValue) && fieldValue.length === 1 && fieldValue[0] === MULTI_VALUE_DEFAULT_VALUE;
|
|
105
|
+
}
|
|
106
|
+
if (fieldType === 'enum') {
|
|
107
|
+
return fieldValue === MULTI_VALUE_DEFAULT_VALUE;
|
|
108
|
+
}
|
|
109
|
+
return false;
|
|
110
|
+
}
|
|
111
|
+
|
|
31
112
|
// Get template instance based on metadata template and selected items
|
|
32
|
-
export function
|
|
113
|
+
export function useTemplateInstance(metadataTemplate: MetadataTemplate, selectedItems: BoxItem[], isEditing: boolean) {
|
|
114
|
+
const { formatMessage } = useIntl();
|
|
33
115
|
const { displayName, fields, hidden, id, scope, templateKey, type } = metadataTemplate;
|
|
34
116
|
|
|
35
117
|
const selectedItemsFields = fields.map(
|
|
36
|
-
({ displayName: fieldDisplayName, hidden: fieldHidden, id: fieldId, key, options, type: fieldType }) =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
118
|
+
({ displayName: fieldDisplayName, hidden: fieldHidden, id: fieldId, key, options, type: fieldType }) => {
|
|
119
|
+
const defaultItemField = {
|
|
120
|
+
displayName: fieldDisplayName,
|
|
121
|
+
hidden: fieldHidden,
|
|
122
|
+
id: fieldId,
|
|
123
|
+
key,
|
|
124
|
+
options,
|
|
125
|
+
type: fieldType,
|
|
126
|
+
value: getFieldValue(fieldType as MetadataFieldType, undefined),
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
const firstSelectedItem = selectedItems[0];
|
|
130
|
+
const firstSelectedItemFieldValue = firstSelectedItem.metadata[scope][templateKey][key];
|
|
131
|
+
|
|
132
|
+
// Case 1: Single selected item
|
|
133
|
+
if (selectedItems.length <= 1) {
|
|
134
|
+
return {
|
|
135
|
+
...defaultItemField,
|
|
136
|
+
value: firstSelectedItemFieldValue,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Case 2.1: Multiple selected items, but all have the same initial value
|
|
141
|
+
const allItemsHaveSameInitialValue = selectedItems.every(selectedItem =>
|
|
142
|
+
areFieldValuesEqual(selectedItem.metadata[scope][templateKey][key], firstSelectedItemFieldValue),
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
if (allItemsHaveSameInitialValue) {
|
|
146
|
+
return {
|
|
147
|
+
...defaultItemField,
|
|
148
|
+
value: getFieldValue(fieldType as MetadataFieldType, firstSelectedItemFieldValue),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Case 2.2: Multiple selected items, but some have different initial values
|
|
153
|
+
// Case 2.2.1: Edit Mode
|
|
154
|
+
if (isEditing) {
|
|
155
|
+
let fieldValue = getFieldValue(fieldType as MetadataFieldType, undefined);
|
|
156
|
+
// Add MultiValue Option if the field is multiSelect or enum
|
|
157
|
+
if (fieldType === 'multiSelect' || fieldType === 'enum') {
|
|
158
|
+
fieldValue = fieldType === 'enum' ? MULTI_VALUE_DEFAULT_VALUE : [MULTI_VALUE_DEFAULT_VALUE];
|
|
159
|
+
const multiValueOption = options?.find(option => option.key === MULTI_VALUE_DEFAULT_VALUE);
|
|
160
|
+
if (!multiValueOption) {
|
|
161
|
+
options?.push(MULTI_VALUE_DEFAULT_OPTION);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
...defaultItemField,
|
|
166
|
+
value: fieldValue,
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Case: 2.2.2 View Mode
|
|
172
|
+
*
|
|
173
|
+
* We want to show "Multiple values" label for multiple dates across files selection.
|
|
174
|
+
* We use fragment here to bypass check in shared feature.
|
|
175
|
+
* This feature tries to parse string as date if the string is passed as value.
|
|
176
|
+
*/
|
|
177
|
+
const multipleValuesText = formatMessage(messages.multipleValues);
|
|
178
|
+
return {
|
|
179
|
+
...defaultItemField,
|
|
180
|
+
value: React.createElement(React.Fragment, null, multipleValuesText),
|
|
181
|
+
};
|
|
182
|
+
},
|
|
46
183
|
);
|
|
47
184
|
|
|
48
185
|
return {
|