box-ui-elements 23.5.0-beta.3 → 24.0.0-beta.1
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/picker.js +1 -1
- package/dist/preview.css +1 -1
- package/dist/preview.js +1 -1
- package/dist/sidebar.css +1 -1
- package/dist/sidebar.js +1 -1
- package/es/constants.js +13 -0
- package/es/constants.js.flow +13 -0
- package/es/constants.js.map +1 -1
- package/es/elements/common/content-answers/ContentAnswersModal.js +1 -3
- package/es/elements/common/content-answers/ContentAnswersModal.js.map +1 -1
- package/es/elements/common/sub-header/SubHeader.js +3 -0
- package/es/elements/common/sub-header/SubHeader.js.map +1 -1
- package/es/elements/common/sub-header/SubHeaderLeftV2.js +3 -23
- package/es/elements/common/sub-header/SubHeaderLeftV2.js.map +1 -1
- package/es/elements/common/sub-header/SubHeaderRight.js +6 -2
- package/es/elements/common/sub-header/SubHeaderRight.js.map +1 -1
- package/es/elements/content-explorer/ContentExplorer.js +55 -10
- package/es/elements/content-explorer/ContentExplorer.js.map +1 -1
- package/es/elements/content-explorer/ContentExplorer.scss +12 -0
- package/es/elements/content-explorer/MetadataSidePanel.js +92 -0
- package/es/elements/content-explorer/MetadataSidePanel.js.map +1 -0
- package/es/elements/content-explorer/MetadataSidePanel.scss +12 -0
- package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js +54 -3
- package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js.map +1 -1
- package/es/elements/content-explorer/utils.js +67 -0
- package/es/elements/content-explorer/utils.js.map +1 -0
- package/es/elements/content-sidebar/BoxAISidebar.js.map +1 -1
- package/es/elements/content-sidebar/BoxAISidebarContent.js +2 -4
- package/es/elements/content-sidebar/BoxAISidebarContent.js.map +1 -1
- package/es/elements/content-sidebar/stories/BoxAISidebar.stories.js +0 -1
- package/es/elements/content-sidebar/stories/BoxAISidebar.stories.js.map +1 -1
- package/es/elements/content-sidebar/stories/tests/BoxAISidebar-visual.stories.js +0 -1
- package/es/elements/content-sidebar/stories/tests/BoxAISidebar-visual.stories.js.map +1 -1
- package/es/src/elements/common/content-answers/ContentAnswersModal.d.ts +0 -1
- package/es/src/elements/common/sub-header/SubHeader.d.ts +2 -1
- package/es/src/elements/common/sub-header/SubHeaderLeftV2.d.ts +1 -1
- package/es/src/elements/common/sub-header/SubHeaderRight.d.ts +4 -1
- package/es/src/elements/content-explorer/ContentExplorer.d.ts +15 -0
- package/es/src/elements/content-explorer/MetadataSidePanel.d.ts +13 -0
- package/es/src/elements/content-explorer/__tests__/MetadataSidePanel.test.d.ts +1 -0
- package/es/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.d.ts +2 -0
- package/es/src/elements/content-explorer/utils.d.ts +22 -0
- package/es/src/elements/content-sidebar/BoxAISidebar.d.ts +0 -1
- package/es/src/elements/content-sidebar/stories/BoxAISidebar.stories.d.ts +0 -1
- package/package.json +2 -2
- package/src/constants.js +13 -0
- package/src/elements/common/content-answers/ContentAnswersModal.tsx +0 -3
- package/src/elements/common/content-answers/__tests__/ContentAnswersModal.test.tsx +7 -2
- package/src/elements/common/sub-header/SubHeader.tsx +4 -0
- package/src/elements/common/sub-header/SubHeaderLeftV2.tsx +3 -22
- package/src/elements/common/sub-header/SubHeaderRight.tsx +8 -2
- package/src/elements/content-explorer/ContentExplorer.scss +12 -0
- package/src/elements/content-explorer/ContentExplorer.tsx +135 -77
- package/src/elements/content-explorer/MetadataSidePanel.scss +12 -0
- package/src/elements/content-explorer/MetadataSidePanel.tsx +126 -0
- package/src/elements/content-explorer/__tests__/ContentExplorer.test.tsx +80 -16
- package/src/elements/content-explorer/__tests__/MetadataSidePanel.test.tsx +127 -0
- package/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx +43 -3
- package/src/elements/content-explorer/utils.ts +58 -0
- package/src/elements/content-sidebar/BoxAISidebar.tsx +0 -1
- package/src/elements/content-sidebar/BoxAISidebarContent.tsx +1 -3
- package/src/elements/content-sidebar/__tests__/BoxAISidebar.test.tsx +0 -8
- package/src/elements/content-sidebar/stories/BoxAISidebar.stories.tsx +0 -1
- package/src/elements/content-sidebar/stories/tests/BoxAISidebar-visual.stories.tsx +0 -1
|
@@ -24,6 +24,7 @@ import ThemingStyles from '../common/theming';
|
|
|
24
24
|
import API from '../../api';
|
|
25
25
|
import MetadataQueryAPIHelperV2 from './MetadataQueryAPIHelper';
|
|
26
26
|
import MetadataQueryAPIHelper from '../../features/metadata-based-view/MetadataQueryAPIHelper';
|
|
27
|
+
import MetadataSidePanel from './MetadataSidePanel';
|
|
27
28
|
import Footer from './Footer';
|
|
28
29
|
import PreviewDialog from '../common/preview-dialog/PreviewDialog';
|
|
29
30
|
import ShareDialog from './ShareDialog';
|
|
@@ -48,6 +49,7 @@ import {
|
|
|
48
49
|
DEFAULT_HOSTNAME_STATIC,
|
|
49
50
|
DEFAULT_SEARCH_DEBOUNCE,
|
|
50
51
|
SORT_ASC,
|
|
52
|
+
FIELD_ITEM_NAME,
|
|
51
53
|
FIELD_NAME,
|
|
52
54
|
FIELD_PERMISSIONS_CAN_SHARE,
|
|
53
55
|
FIELD_SHARED_LINK,
|
|
@@ -169,6 +171,7 @@ type State = {
|
|
|
169
171
|
isCreateFolderModalOpen: boolean;
|
|
170
172
|
isDeleteModalOpen: boolean;
|
|
171
173
|
isLoading: boolean;
|
|
174
|
+
isMetadataSidePanelOpen: boolean;
|
|
172
175
|
isPreviewModalOpen: boolean;
|
|
173
176
|
isRenameModalOpen: boolean;
|
|
174
177
|
isShareModalOpen: boolean;
|
|
@@ -294,6 +297,7 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
294
297
|
isCreateFolderModalOpen: false,
|
|
295
298
|
isDeleteModalOpen: false,
|
|
296
299
|
isLoading: false,
|
|
300
|
+
isMetadataSidePanelOpen: false,
|
|
297
301
|
isPreviewModalOpen: false,
|
|
298
302
|
isRenameModalOpen: false,
|
|
299
303
|
isShareModalOpen: false,
|
|
@@ -451,12 +455,6 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
451
455
|
metadataQueryClone.limit = DEFAULT_PAGE_SIZE;
|
|
452
456
|
}
|
|
453
457
|
|
|
454
|
-
metadataQueryClone.order_by = [
|
|
455
|
-
{
|
|
456
|
-
field_key: sortBy,
|
|
457
|
-
direction: sortDirection,
|
|
458
|
-
},
|
|
459
|
-
];
|
|
460
458
|
// Reset search state, the view and show busy indicator
|
|
461
459
|
this.setState({
|
|
462
460
|
searchQuery: '',
|
|
@@ -465,8 +463,22 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
465
463
|
});
|
|
466
464
|
|
|
467
465
|
if (isFeatureEnabled(features, 'contentExplorer.metadataViewV2')) {
|
|
466
|
+
metadataQueryClone.order_by = [
|
|
467
|
+
{
|
|
468
|
+
// Default to the prefixed name field for metadata view v2 only, while not touching the default sortBy for other views.
|
|
469
|
+
field_key: sortBy === FIELD_NAME ? FIELD_ITEM_NAME : sortBy,
|
|
470
|
+
direction: sortDirection,
|
|
471
|
+
},
|
|
472
|
+
];
|
|
473
|
+
|
|
468
474
|
this.metadataQueryAPIHelper = new MetadataQueryAPIHelperV2(this.api);
|
|
469
475
|
} else {
|
|
476
|
+
metadataQueryClone.order_by = [
|
|
477
|
+
{
|
|
478
|
+
field_key: sortBy,
|
|
479
|
+
direction: sortDirection,
|
|
480
|
+
},
|
|
481
|
+
];
|
|
470
482
|
this.metadataQueryAPIHelper = new MetadataQueryAPIHelper(this.api);
|
|
471
483
|
}
|
|
472
484
|
|
|
@@ -1562,7 +1574,11 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
1562
1574
|
selectedKeys: selectedItemIds,
|
|
1563
1575
|
onSelectionChange: (ids: Selection) => {
|
|
1564
1576
|
onSelectionChange?.(ids);
|
|
1565
|
-
|
|
1577
|
+
const isSelectionEmpty = ids !== 'all' && ids.size === 0;
|
|
1578
|
+
this.setState({
|
|
1579
|
+
selectedItemIds: ids,
|
|
1580
|
+
...(isSelectionEmpty && { isMetadataSidePanelOpen: false }),
|
|
1581
|
+
});
|
|
1566
1582
|
},
|
|
1567
1583
|
},
|
|
1568
1584
|
};
|
|
@@ -1644,7 +1660,32 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
1644
1660
|
};
|
|
1645
1661
|
|
|
1646
1662
|
clearSelectedItemIds = () => {
|
|
1647
|
-
this.setState({
|
|
1663
|
+
this.setState({
|
|
1664
|
+
selectedItemIds: new Set(),
|
|
1665
|
+
isMetadataSidePanelOpen: false,
|
|
1666
|
+
});
|
|
1667
|
+
};
|
|
1668
|
+
|
|
1669
|
+
/**
|
|
1670
|
+
* Toggle metadata side panel visibility
|
|
1671
|
+
*
|
|
1672
|
+
* @private
|
|
1673
|
+
* @return {void}
|
|
1674
|
+
*/
|
|
1675
|
+
onMetadataSidePanelToggle = () => {
|
|
1676
|
+
this.setState(prevState => ({
|
|
1677
|
+
isMetadataSidePanelOpen: !prevState.isMetadataSidePanelOpen,
|
|
1678
|
+
}));
|
|
1679
|
+
};
|
|
1680
|
+
|
|
1681
|
+
/**
|
|
1682
|
+
* Close metadata side panel
|
|
1683
|
+
*
|
|
1684
|
+
* @private
|
|
1685
|
+
* @return {void}
|
|
1686
|
+
*/
|
|
1687
|
+
closeMetadataSidePanel = () => {
|
|
1688
|
+
this.setState({ isMetadataSidePanelOpen: false });
|
|
1648
1689
|
};
|
|
1649
1690
|
|
|
1650
1691
|
/**
|
|
@@ -1706,6 +1747,7 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
1706
1747
|
isCreateFolderModalOpen,
|
|
1707
1748
|
isDeleteModalOpen,
|
|
1708
1749
|
isLoading,
|
|
1750
|
+
isMetadataSidePanelOpen,
|
|
1709
1751
|
isPreviewModalOpen,
|
|
1710
1752
|
isRenameModalOpen,
|
|
1711
1753
|
isShareModalOpen,
|
|
@@ -1714,6 +1756,7 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
1714
1756
|
metadataTemplate,
|
|
1715
1757
|
rootName,
|
|
1716
1758
|
selected,
|
|
1759
|
+
selectedItemIds,
|
|
1717
1760
|
view,
|
|
1718
1761
|
}: State = this.state;
|
|
1719
1762
|
|
|
@@ -1723,6 +1766,7 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
1723
1766
|
const allowUpload: boolean = canUpload && !!can_upload;
|
|
1724
1767
|
const allowCreate: boolean = canCreateNewFolder && !!can_upload;
|
|
1725
1768
|
const isDefaultViewMetadata: boolean = defaultView === DEFAULT_VIEW_METADATA;
|
|
1769
|
+
const isMetadataViewV2Feature = isFeatureEnabled(features, 'contentExplorer.metadataViewV2');
|
|
1726
1770
|
const isErrorView: boolean = view === VIEW_ERROR;
|
|
1727
1771
|
|
|
1728
1772
|
const viewMode = this.getViewMode();
|
|
@@ -1741,75 +1785,89 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
1741
1785
|
<div id={this.id} className={styleClassName} ref={measureRef} data-testid="content-explorer">
|
|
1742
1786
|
<ThemingStyles selector={`#${this.id}`} theme={theme} />
|
|
1743
1787
|
<div className="be-app-element" onKeyDown={this.onKeyDown} tabIndex={0}>
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1788
|
+
<div className="bce-ContentExplorer-main">
|
|
1789
|
+
{!isDefaultViewMetadata && (
|
|
1790
|
+
<Header view={view} logoUrl={logoUrl} onSearch={this.search} />
|
|
1791
|
+
)}
|
|
1792
|
+
|
|
1793
|
+
<SubHeader
|
|
1794
|
+
view={view}
|
|
1795
|
+
viewMode={viewMode}
|
|
1796
|
+
rootId={rootFolderId}
|
|
1797
|
+
isSmall={isSmall}
|
|
1798
|
+
rootName={rootName}
|
|
1799
|
+
currentCollection={currentCollection}
|
|
1800
|
+
canUpload={allowUpload}
|
|
1801
|
+
canCreateNewFolder={allowCreate}
|
|
1802
|
+
gridColumnCount={gridColumnCount}
|
|
1803
|
+
gridMaxColumns={GRID_VIEW_MAX_COLUMNS}
|
|
1804
|
+
gridMinColumns={GRID_VIEW_MIN_COLUMNS}
|
|
1805
|
+
maxGridColumnCountForWidth={maxGridColumnCount}
|
|
1806
|
+
onUpload={this.upload}
|
|
1807
|
+
onClearSelectedItemIds={this.clearSelectedItemIds}
|
|
1808
|
+
onCreate={this.createFolder}
|
|
1809
|
+
onGridViewSliderChange={this.onGridViewSliderChange}
|
|
1810
|
+
onItemClick={this.fetchFolder}
|
|
1811
|
+
onSortChange={this.sort}
|
|
1812
|
+
onMetadataSidePanelToggle={this.onMetadataSidePanelToggle}
|
|
1813
|
+
onViewModeChange={this.changeViewMode}
|
|
1814
|
+
portalElement={this.rootElement}
|
|
1815
|
+
selectedItemIds={selectedItemIds}
|
|
1816
|
+
title={title}
|
|
1817
|
+
/>
|
|
1818
|
+
|
|
1819
|
+
<Content
|
|
1820
|
+
canDelete={canDelete}
|
|
1821
|
+
canDownload={canDownload}
|
|
1822
|
+
canPreview={canPreview}
|
|
1823
|
+
canRename={canRename}
|
|
1824
|
+
canShare={canShare}
|
|
1825
|
+
currentCollection={currentCollection}
|
|
1826
|
+
features={features}
|
|
1827
|
+
gridColumnCount={Math.min(gridColumnCount, maxGridColumnCount)}
|
|
1828
|
+
isMedium={isMedium}
|
|
1829
|
+
isSmall={isSmall}
|
|
1830
|
+
isTouch={isTouch}
|
|
1831
|
+
itemActions={itemActions}
|
|
1832
|
+
fieldsToShow={fieldsToShow}
|
|
1833
|
+
metadataTemplate={metadataTemplate}
|
|
1834
|
+
metadataViewProps={metadataViewProps}
|
|
1835
|
+
onItemClick={this.onItemClick}
|
|
1836
|
+
onItemDelete={this.delete}
|
|
1837
|
+
onItemDownload={this.download}
|
|
1838
|
+
onItemPreview={this.preview}
|
|
1839
|
+
onItemRename={this.rename}
|
|
1840
|
+
onItemSelect={this.select}
|
|
1841
|
+
onItemShare={this.share}
|
|
1842
|
+
onMetadataUpdate={this.updateMetadata}
|
|
1843
|
+
onSortChange={this.sort}
|
|
1844
|
+
portalElement={this.rootElement}
|
|
1845
|
+
view={view}
|
|
1846
|
+
viewMode={viewMode}
|
|
1847
|
+
/>
|
|
1848
|
+
|
|
1849
|
+
{!isErrorView && (
|
|
1850
|
+
<Footer>
|
|
1851
|
+
<Pagination
|
|
1852
|
+
hasNextMarker={hasNextMarker}
|
|
1853
|
+
hasPrevMarker={hasPreviousMarker}
|
|
1854
|
+
isSmall={isSmall}
|
|
1855
|
+
offset={offset}
|
|
1856
|
+
onOffsetChange={this.paginate}
|
|
1857
|
+
pageSize={currentPageSize}
|
|
1858
|
+
totalCount={totalCount}
|
|
1859
|
+
onMarkerBasedPageChange={this.markerBasedPaginate}
|
|
1860
|
+
/>
|
|
1861
|
+
</Footer>
|
|
1862
|
+
)}
|
|
1863
|
+
</div>
|
|
1864
|
+
{isDefaultViewMetadata && isMetadataViewV2Feature && isMetadataSidePanelOpen && (
|
|
1865
|
+
<MetadataSidePanel
|
|
1866
|
+
currentCollection={currentCollection}
|
|
1867
|
+
onClose={this.closeMetadataSidePanel}
|
|
1868
|
+
metadataTemplate={metadataTemplate}
|
|
1869
|
+
selectedItemIds={selectedItemIds}
|
|
1870
|
+
/>
|
|
1813
1871
|
)}
|
|
1814
1872
|
</div>
|
|
1815
1873
|
{allowUpload && !!this.appElement ? (
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
|
+
|
|
4
|
+
import { IconButton, SidePanel, Text } from '@box/blueprint-web';
|
|
5
|
+
import { XMark } from '@box/blueprint-web-assets/icons/Fill/index';
|
|
6
|
+
import { FileDefault } from '@box/blueprint-web-assets/icons/Line/index';
|
|
7
|
+
import {
|
|
8
|
+
AutofillContextProvider,
|
|
9
|
+
FormValues,
|
|
10
|
+
JSONPatchOperations,
|
|
11
|
+
MetadataInstance,
|
|
12
|
+
MetadataInstanceForm,
|
|
13
|
+
} from '@box/metadata-editor';
|
|
14
|
+
|
|
15
|
+
import type { Selection } from 'react-aria-components';
|
|
16
|
+
import type { Collection } from '../../common/types/core';
|
|
17
|
+
import type { MetadataTemplate } from '../../common/types/metadata';
|
|
18
|
+
import { getTemplateInstance, useSelectedItemText } from './utils';
|
|
19
|
+
|
|
20
|
+
import messages from '../common/messages';
|
|
21
|
+
|
|
22
|
+
import './MetadataSidePanel.scss';
|
|
23
|
+
|
|
24
|
+
export interface MetadataSidePanelProps {
|
|
25
|
+
currentCollection: Collection;
|
|
26
|
+
onClose: () => void;
|
|
27
|
+
metadataTemplate: MetadataTemplate;
|
|
28
|
+
selectedItemIds: Selection;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const MetadataSidePanel = ({
|
|
32
|
+
currentCollection,
|
|
33
|
+
onClose,
|
|
34
|
+
selectedItemIds,
|
|
35
|
+
metadataTemplate,
|
|
36
|
+
}: MetadataSidePanelProps) => {
|
|
37
|
+
const { formatMessage } = useIntl();
|
|
38
|
+
const [isEditing, setIsEditing] = useState<boolean>(false);
|
|
39
|
+
const [isUnsavedChangesModalOpen, setIsUnsavedChangesModalOpen] = useState<boolean>(false);
|
|
40
|
+
|
|
41
|
+
const selectedItemText = useSelectedItemText(currentCollection, selectedItemIds);
|
|
42
|
+
const selectedItems =
|
|
43
|
+
selectedItemIds === 'all'
|
|
44
|
+
? currentCollection.items
|
|
45
|
+
: currentCollection.items.filter(item => selectedItemIds.has(item.id));
|
|
46
|
+
const templateInstance = getTemplateInstance(metadataTemplate, selectedItems);
|
|
47
|
+
|
|
48
|
+
const handleMetadataInstanceEdit = () => {
|
|
49
|
+
setIsEditing(true);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const handleMetadataInstanceFormCancel = () => {
|
|
53
|
+
setIsEditing(false);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
57
|
+
const handleMetadataInstanceFormChange = (values: FormValues) => {
|
|
58
|
+
// TODO: Implement on form change
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const handleMetadataInstanceFormDiscardUnsavedChanges = () => {
|
|
62
|
+
setIsUnsavedChangesModalOpen(false);
|
|
63
|
+
setIsEditing(false);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
67
|
+
const handleMetadataInstanceFormSubmit = async (values: FormValues, operations: JSONPatchOperations) => {
|
|
68
|
+
// TODO: Implement onSave callback
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<SidePanel variant="persistent">
|
|
73
|
+
<SidePanel.Header>
|
|
74
|
+
<div>
|
|
75
|
+
<Text as="span" variant="titleLarge">
|
|
76
|
+
{formatMessage(messages.sidebarMetadataTitle)}
|
|
77
|
+
</Text>
|
|
78
|
+
<div className="bce-MetadataSidePanel-subtitle">
|
|
79
|
+
<FileDefault />
|
|
80
|
+
<Text as="span" color="textOnLightSecondary" variant="subtitle">
|
|
81
|
+
{selectedItemText}
|
|
82
|
+
</Text>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
<IconButton aria-label={formatMessage(messages.close)} icon={XMark} onClick={onClose} size="large" />
|
|
86
|
+
</SidePanel.Header>
|
|
87
|
+
<SidePanel.ScrollableContainer>
|
|
88
|
+
<div className="bce-MetadataSidePanel-content">
|
|
89
|
+
<AutofillContextProvider fetchSuggestions={null} isAiSuggestionsFeatureEnabled={false}>
|
|
90
|
+
{isEditing ? (
|
|
91
|
+
<MetadataInstanceForm
|
|
92
|
+
areAiSuggestionsAvailable={false}
|
|
93
|
+
isAiSuggestionsFeatureEnabled={false}
|
|
94
|
+
isBetaLanguageEnabled={false}
|
|
95
|
+
isDeleteButtonDisabled={true}
|
|
96
|
+
isDeleteConfirmationModalCheckboxEnabled={false}
|
|
97
|
+
isLargeFile={false}
|
|
98
|
+
isMultilevelTaxonomyFieldEnabled={false}
|
|
99
|
+
isUnsavedChangesModalOpen={isUnsavedChangesModalOpen}
|
|
100
|
+
selectedTemplateInstance={templateInstance}
|
|
101
|
+
onCancel={handleMetadataInstanceFormCancel}
|
|
102
|
+
onChange={handleMetadataInstanceFormChange}
|
|
103
|
+
onDelete={null}
|
|
104
|
+
onDiscardUnsavedChanges={handleMetadataInstanceFormDiscardUnsavedChanges}
|
|
105
|
+
onSubmit={handleMetadataInstanceFormSubmit}
|
|
106
|
+
setIsUnsavedChangesModalOpen={setIsUnsavedChangesModalOpen}
|
|
107
|
+
taxonomyOptionsFetcher={null}
|
|
108
|
+
/>
|
|
109
|
+
) : (
|
|
110
|
+
<MetadataInstance
|
|
111
|
+
areAiSuggestionsAvailable={false}
|
|
112
|
+
isAiSuggestionsFeatureEnabled={false}
|
|
113
|
+
isBetaLanguageEnabled={false}
|
|
114
|
+
onEdit={handleMetadataInstanceEdit}
|
|
115
|
+
templateInstance={templateInstance}
|
|
116
|
+
taxonomyNodeFetcher={null}
|
|
117
|
+
/>
|
|
118
|
+
)}
|
|
119
|
+
</AutofillContextProvider>
|
|
120
|
+
</div>
|
|
121
|
+
</SidePanel.ScrollableContainer>
|
|
122
|
+
</SidePanel>
|
|
123
|
+
);
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export default MetadataSidePanel;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import userEvent from '@testing-library/user-event';
|
|
3
|
+
import type { MetadataFieldType } from '@box/metadata-view';
|
|
4
|
+
|
|
3
5
|
import { render, screen, waitFor, within } from '../../../test-utils/testing-library';
|
|
4
6
|
import { ContentExplorerComponent as ContentExplorer, ContentExplorerProps } from '../ContentExplorer';
|
|
5
7
|
import { mockRecentItems, mockRootFolder, mockRootFolderSharedLink } from '../../common/__mocks__/mockRootFolder';
|
|
@@ -77,7 +79,13 @@ describe('elements/content-explorer/ContentExplorer', () => {
|
|
|
77
79
|
const renderComponent = ({ features, ...props }: Partial<ContentExplorerProps> = {}) => {
|
|
78
80
|
return render(
|
|
79
81
|
<FeatureProvider features={features}>
|
|
80
|
-
<ContentExplorer
|
|
82
|
+
<ContentExplorer
|
|
83
|
+
defaultView="list"
|
|
84
|
+
features={features}
|
|
85
|
+
rootFolderId="69083462919"
|
|
86
|
+
token="token"
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
81
89
|
</FeatureProvider>,
|
|
82
90
|
);
|
|
83
91
|
};
|
|
@@ -414,31 +422,87 @@ describe('elements/content-explorer/ContentExplorer', () => {
|
|
|
414
422
|
expect(screen.getByText('Technology')).toBeInTheDocument();
|
|
415
423
|
expect(screen.getByText('November 16, 2023')).toBeInTheDocument();
|
|
416
424
|
});
|
|
425
|
+
|
|
417
426
|
describe('Metadata View V2', () => {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
427
|
+
const { scope: templateScope, templateKey } = mockSchema;
|
|
428
|
+
const metadataScopeAndKey = `${templateScope}.${templateKey}`;
|
|
429
|
+
const metadataFieldNamePrefix = `metadata.${metadataScopeAndKey}`;
|
|
430
|
+
const metadataQuery = {
|
|
431
|
+
from: metadataScopeAndKey,
|
|
432
|
+
ancestor_folder_id: '69083462919',
|
|
433
|
+
sort_by: [
|
|
434
|
+
{
|
|
435
|
+
field_key: `${metadataFieldNamePrefix}.${mockSchema.fields[0].key}`, // Default to sorting by the first field in the schema
|
|
436
|
+
direction: 'asc',
|
|
437
|
+
},
|
|
438
|
+
],
|
|
439
|
+
fields: [
|
|
440
|
+
// Default to returning all fields in the metadata template schema, and name as a standalone (non-metadata) field
|
|
441
|
+
...mockSchema.fields.map(field => `${metadataFieldNamePrefix}.${field.key}`),
|
|
442
|
+
'name',
|
|
443
|
+
],
|
|
444
|
+
};
|
|
445
|
+
const fieldsToShow = [
|
|
446
|
+
{ key: `${metadataFieldNamePrefix}.name`, canEdit: false, displayName: 'Alias' },
|
|
447
|
+
{ key: `${metadataFieldNamePrefix}.industry`, canEdit: true },
|
|
448
|
+
{ key: `${metadataFieldNamePrefix}.last_contacted_at`, canEdit: true },
|
|
449
|
+
{ key: `${metadataFieldNamePrefix}.role`, canEdit: true },
|
|
450
|
+
];
|
|
451
|
+
const columns = [
|
|
452
|
+
{
|
|
453
|
+
// Always include the name column
|
|
454
|
+
textValue: 'Name',
|
|
455
|
+
id: 'name',
|
|
456
|
+
type: 'string' as const,
|
|
457
|
+
allowSorting: true,
|
|
458
|
+
minWidth: 150,
|
|
459
|
+
maxWidth: 150,
|
|
460
|
+
},
|
|
461
|
+
...mockSchema.fields.map(field => ({
|
|
462
|
+
textValue: field.displayName,
|
|
463
|
+
id: `${metadataFieldNamePrefix}.${field.key}`,
|
|
464
|
+
type: field.type as MetadataFieldType,
|
|
465
|
+
allowSorting: true,
|
|
466
|
+
minWidth: 150,
|
|
467
|
+
maxWidth: 150,
|
|
468
|
+
})),
|
|
469
|
+
];
|
|
470
|
+
const defaultView = 'metadata';
|
|
471
|
+
const metadataViewV2ElementProps = {
|
|
472
|
+
metadataViewProps: {
|
|
473
|
+
columns,
|
|
474
|
+
metadataTemplate: mockSchema,
|
|
475
|
+
tableProps: {
|
|
476
|
+
isSelectAllEnabled: true,
|
|
425
477
|
},
|
|
478
|
+
},
|
|
479
|
+
metadataQuery,
|
|
480
|
+
fieldsToShow,
|
|
481
|
+
defaultView,
|
|
482
|
+
features: {
|
|
483
|
+
contentExplorer: {
|
|
484
|
+
metadataViewV2: true,
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
};
|
|
488
|
+
|
|
489
|
+
test('should render metadata view button', async () => {
|
|
490
|
+
renderComponent(metadataViewV2ElementProps);
|
|
491
|
+
await waitFor(() => {
|
|
492
|
+
expect(screen.getByTestId('content-explorer')).toBeInTheDocument();
|
|
426
493
|
});
|
|
427
494
|
|
|
428
|
-
// two separate promises need to be resolved before the component is ready
|
|
429
495
|
await waitFor(() => {
|
|
430
|
-
expect(screen.
|
|
496
|
+
expect(screen.queryByRole('button', { name: 'Switch to Grid View' })).toBeInTheDocument();
|
|
431
497
|
});
|
|
432
498
|
|
|
433
499
|
await waitFor(() => {
|
|
434
|
-
expect(screen.
|
|
500
|
+
expect(screen.getByRole('row', { name: /Child 2/i })).toBeInTheDocument();
|
|
435
501
|
});
|
|
436
502
|
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
expect(screen.queryByRole('button', { name: 'Sort' })).not.toBeInTheDocument();
|
|
441
|
-
expect(screen.queryByRole('button', { name: 'Add' })).not.toBeInTheDocument();
|
|
503
|
+
const selectAllCheckbox = screen.getByLabelText('Select all');
|
|
504
|
+
await userEvent.click(selectAllCheckbox);
|
|
505
|
+
|
|
442
506
|
expect(screen.getByRole('button', { name: 'Metadata' })).toBeInTheDocument();
|
|
443
507
|
});
|
|
444
508
|
});
|