box-ui-elements 24.0.0-beta.4 → 24.0.0-beta.5
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.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 +2 -1
- package/es/elements/content-explorer/Content.js.map +1 -1
- package/es/elements/content-explorer/ContentExplorer.js +19 -5
- package/es/elements/content-explorer/ContentExplorer.js.map +1 -1
- package/es/elements/content-explorer/MetadataQueryAPIHelper.js +61 -4
- package/es/elements/content-explorer/MetadataQueryAPIHelper.js.map +1 -1
- 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 +55 -4
- package/es/elements/content-explorer/MetadataViewContainer.js.map +1 -1
- package/es/elements/content-explorer/stories/tests/MetadataView-visual.stories.js +61 -13
- 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/content-explorer/ContentExplorer.d.ts +11 -3
- package/es/src/elements/content-explorer/MetadataQueryAPIHelper.d.ts +11 -1
- package/es/src/elements/content-explorer/MetadataSidePanel.d.ts +6 -3
- package/es/src/elements/content-explorer/MetadataViewContainer.d.ts +3 -1
- 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 +4 -0
- package/i18n/da-DK.js +4 -0
- package/i18n/da-DK.properties +4 -0
- package/i18n/de-DE.js +5 -1
- package/i18n/de-DE.properties +4 -0
- package/i18n/en-AU.js +4 -0
- package/i18n/en-AU.properties +4 -0
- package/i18n/en-CA.js +4 -0
- package/i18n/en-CA.properties +4 -0
- package/i18n/en-GB.js +4 -0
- package/i18n/en-GB.properties +4 -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 +4 -0
- package/i18n/es-ES.js +5 -1
- package/i18n/es-ES.properties +4 -0
- package/i18n/fi-FI.js +4 -0
- package/i18n/fi-FI.properties +4 -0
- package/i18n/fr-CA.js +4 -0
- package/i18n/fr-CA.properties +4 -0
- package/i18n/fr-FR.js +4 -0
- package/i18n/fr-FR.properties +4 -0
- package/i18n/hi-IN.js +4 -0
- package/i18n/hi-IN.properties +4 -0
- package/i18n/it-IT.js +4 -0
- package/i18n/it-IT.properties +4 -0
- package/i18n/ja-JP.js +6 -2
- package/i18n/ja-JP.properties +6 -2
- package/i18n/ko-KR.js +4 -0
- package/i18n/ko-KR.properties +4 -0
- package/i18n/nb-NO.js +4 -0
- package/i18n/nb-NO.properties +4 -0
- package/i18n/nl-NL.js +4 -0
- package/i18n/nl-NL.properties +4 -0
- package/i18n/pl-PL.js +4 -0
- package/i18n/pl-PL.properties +4 -0
- package/i18n/pt-BR.js +4 -0
- package/i18n/pt-BR.properties +4 -0
- package/i18n/ru-RU.js +5 -1
- package/i18n/ru-RU.properties +4 -0
- package/i18n/sv-SE.js +4 -0
- package/i18n/sv-SE.properties +4 -0
- package/i18n/tr-TR.js +5 -1
- package/i18n/tr-TR.properties +4 -0
- package/i18n/zh-CN.js +4 -0
- package/i18n/zh-CN.properties +4 -0
- package/i18n/zh-TW.js +4 -0
- package/i18n/zh-TW.properties +4 -0
- package/package.json +1 -1
- package/src/api/Metadata.js +110 -12
- package/src/api/__tests__/Metadata.test.js +120 -0
- package/src/elements/common/messages.js +25 -0
- package/src/elements/content-explorer/Content.tsx +1 -0
- package/src/elements/content-explorer/ContentExplorer.tsx +220 -181
- package/src/elements/content-explorer/MetadataQueryAPIHelper.ts +89 -4
- package/src/elements/content-explorer/MetadataSidePanel.tsx +55 -14
- package/src/elements/content-explorer/MetadataViewContainer.tsx +61 -1
- package/src/elements/content-explorer/__tests__/ContentExplorer.test.tsx +36 -2
- package/src/elements/content-explorer/__tests__/MetadataQueryAPIHelper.test.ts +8 -5
- package/src/elements/content-explorer/__tests__/MetadataSidePanel.test.tsx +145 -3
- package/src/elements/content-explorer/stories/tests/MetadataView-visual.stories.tsx +54 -8
- package/src/elements/content-explorer/utils.ts +150 -13
|
@@ -8,9 +8,10 @@ import getProp from 'lodash/get';
|
|
|
8
8
|
import noop from 'lodash/noop';
|
|
9
9
|
import throttle from 'lodash/throttle';
|
|
10
10
|
import uniqueid from 'lodash/uniqueId';
|
|
11
|
-
import { TooltipProvider } from '@box/blueprint-web';
|
|
11
|
+
import { Notification, TooltipProvider } from '@box/blueprint-web';
|
|
12
12
|
import { AxiosRequestConfig, AxiosResponse } from 'axios';
|
|
13
|
-
import type { Selection } from 'react-aria-components';
|
|
13
|
+
import type { Key, Selection } from 'react-aria-components';
|
|
14
|
+
import type { MetadataTemplateField } from '@box/metadata-editor';
|
|
14
15
|
|
|
15
16
|
import CreateFolderDialog from '../common/create-folder-dialog';
|
|
16
17
|
import UploadDialog from '../common/upload-dialog';
|
|
@@ -77,6 +78,7 @@ import {
|
|
|
77
78
|
import type { ViewMode } from '../common/flowTypes';
|
|
78
79
|
import type { ItemAction } from '../common/item';
|
|
79
80
|
import type { Theme } from '../common/theming';
|
|
81
|
+
import type { JSONPatchOperations } from '../../common/types/api';
|
|
80
82
|
import type { MetadataQuery, FieldsToShow } from '../../common/types/metadataQueries';
|
|
81
83
|
import type { MetadataFieldValue, MetadataTemplate } from '../../common/types/metadata';
|
|
82
84
|
import type {
|
|
@@ -153,7 +155,7 @@ export interface ContentExplorerProps {
|
|
|
153
155
|
rootFolderId?: string;
|
|
154
156
|
sharedLink?: string;
|
|
155
157
|
sharedLinkPassword?: string;
|
|
156
|
-
sortBy?: SortBy;
|
|
158
|
+
sortBy?: SortBy | Key;
|
|
157
159
|
sortDirection?: SortDirection;
|
|
158
160
|
staticHost?: string;
|
|
159
161
|
staticPath?: string;
|
|
@@ -492,6 +494,38 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
492
494
|
);
|
|
493
495
|
}
|
|
494
496
|
|
|
497
|
+
/**
|
|
498
|
+
* Update selected items' metadata instances based on original and new field values in the metadata instance form
|
|
499
|
+
*
|
|
500
|
+
* @private
|
|
501
|
+
* @return {void}
|
|
502
|
+
*/
|
|
503
|
+
updateMetadataV2 = async (
|
|
504
|
+
items: BoxItem[],
|
|
505
|
+
operations: JSONPatchOperations,
|
|
506
|
+
templateOldFields: MetadataTemplateField[],
|
|
507
|
+
templateNewFields: MetadataTemplateField[],
|
|
508
|
+
successCallback: () => void,
|
|
509
|
+
errorCallback: ErrorCallback,
|
|
510
|
+
) => {
|
|
511
|
+
if (items.length === 1) {
|
|
512
|
+
await this.metadataQueryAPIHelper.updateMetadataWithOperations(
|
|
513
|
+
items[0],
|
|
514
|
+
operations,
|
|
515
|
+
successCallback,
|
|
516
|
+
errorCallback,
|
|
517
|
+
);
|
|
518
|
+
} else {
|
|
519
|
+
await this.metadataQueryAPIHelper.bulkUpdateMetadata(
|
|
520
|
+
items,
|
|
521
|
+
templateOldFields,
|
|
522
|
+
templateNewFields,
|
|
523
|
+
successCallback,
|
|
524
|
+
errorCallback,
|
|
525
|
+
);
|
|
526
|
+
}
|
|
527
|
+
};
|
|
528
|
+
|
|
495
529
|
/**
|
|
496
530
|
* Resets the collection so that the loading bar starts showing
|
|
497
531
|
*
|
|
@@ -896,7 +930,7 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
896
930
|
* @param {string} sortDirection - sort direction
|
|
897
931
|
* @return {void}
|
|
898
932
|
*/
|
|
899
|
-
sort = (sortBy: SortBy, sortDirection: SortDirection) => {
|
|
933
|
+
sort = (sortBy: SortBy | Key, sortDirection: SortDirection) => {
|
|
900
934
|
const {
|
|
901
935
|
currentCollection: { id },
|
|
902
936
|
view,
|
|
@@ -1785,188 +1819,193 @@ class ContentExplorer extends Component<ContentExplorerProps, State> {
|
|
|
1785
1819
|
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
|
|
1786
1820
|
return (
|
|
1787
1821
|
<Internationalize language={language} messages={messages}>
|
|
1788
|
-
<
|
|
1789
|
-
<
|
|
1790
|
-
|
|
1791
|
-
<div
|
|
1792
|
-
<
|
|
1793
|
-
|
|
1794
|
-
|
|
1822
|
+
<Notification.Provider>
|
|
1823
|
+
<Notification.Viewport />
|
|
1824
|
+
<TooltipProvider container={this.rootElement}>
|
|
1825
|
+
<div id={this.id} className={styleClassName} ref={measureRef} data-testid="content-explorer">
|
|
1826
|
+
<ThemingStyles selector={`#${this.id}`} theme={theme} />
|
|
1827
|
+
<div className="be-app-element" onKeyDown={this.onKeyDown} tabIndex={0}>
|
|
1828
|
+
<div className="bce-ContentExplorer-main">
|
|
1829
|
+
{!isDefaultViewMetadata && (
|
|
1830
|
+
<Header view={view} logoUrl={logoUrl} onSearch={this.search} />
|
|
1831
|
+
)}
|
|
1832
|
+
|
|
1833
|
+
<SubHeader
|
|
1834
|
+
bulkItemActions={bulkItemActions}
|
|
1835
|
+
view={view}
|
|
1836
|
+
viewMode={viewMode}
|
|
1837
|
+
rootId={rootFolderId}
|
|
1838
|
+
isSmall={isSmall}
|
|
1839
|
+
rootName={rootName}
|
|
1840
|
+
currentCollection={currentCollection}
|
|
1841
|
+
canUpload={allowUpload}
|
|
1842
|
+
canCreateNewFolder={allowCreate}
|
|
1843
|
+
gridColumnCount={gridColumnCount}
|
|
1844
|
+
gridMaxColumns={GRID_VIEW_MAX_COLUMNS}
|
|
1845
|
+
gridMinColumns={GRID_VIEW_MIN_COLUMNS}
|
|
1846
|
+
maxGridColumnCountForWidth={maxGridColumnCount}
|
|
1847
|
+
onUpload={this.upload}
|
|
1848
|
+
onClearSelectedItemIds={this.clearSelectedItemIds}
|
|
1849
|
+
onCreate={this.createFolder}
|
|
1850
|
+
onGridViewSliderChange={this.onGridViewSliderChange}
|
|
1851
|
+
onItemClick={this.fetchFolder}
|
|
1852
|
+
onSortChange={this.sort}
|
|
1853
|
+
onMetadataSidePanelToggle={this.onMetadataSidePanelToggle}
|
|
1854
|
+
onViewModeChange={this.changeViewMode}
|
|
1855
|
+
portalElement={this.rootElement}
|
|
1856
|
+
selectedItemIds={selectedItemIds}
|
|
1857
|
+
title={title}
|
|
1858
|
+
/>
|
|
1859
|
+
|
|
1860
|
+
<Content
|
|
1861
|
+
canDelete={canDelete}
|
|
1862
|
+
canDownload={canDownload}
|
|
1863
|
+
canPreview={canPreview}
|
|
1864
|
+
canRename={canRename}
|
|
1865
|
+
canShare={canShare}
|
|
1866
|
+
currentCollection={currentCollection}
|
|
1867
|
+
features={features}
|
|
1868
|
+
gridColumnCount={Math.min(gridColumnCount, maxGridColumnCount)}
|
|
1869
|
+
isMedium={isMedium}
|
|
1870
|
+
isSmall={isSmall}
|
|
1871
|
+
isTouch={isTouch}
|
|
1872
|
+
itemActions={itemActions}
|
|
1873
|
+
fieldsToShow={fieldsToShow}
|
|
1874
|
+
metadataTemplate={metadataTemplate}
|
|
1875
|
+
metadataViewProps={metadataViewProps}
|
|
1876
|
+
onItemClick={this.onItemClick}
|
|
1877
|
+
onItemDelete={this.delete}
|
|
1878
|
+
onItemDownload={this.download}
|
|
1879
|
+
onItemPreview={this.preview}
|
|
1880
|
+
onItemRename={this.rename}
|
|
1881
|
+
onItemSelect={this.select}
|
|
1882
|
+
onItemShare={this.share}
|
|
1883
|
+
onMetadataUpdate={this.updateMetadata}
|
|
1884
|
+
onSortChange={this.sort}
|
|
1885
|
+
portalElement={this.rootElement}
|
|
1886
|
+
view={view}
|
|
1887
|
+
viewMode={viewMode}
|
|
1888
|
+
/>
|
|
1889
|
+
|
|
1890
|
+
{!isErrorView && (
|
|
1891
|
+
<Footer>
|
|
1892
|
+
<Pagination
|
|
1893
|
+
hasNextMarker={hasNextMarker}
|
|
1894
|
+
hasPrevMarker={hasPreviousMarker}
|
|
1895
|
+
isSmall={isSmall}
|
|
1896
|
+
offset={offset}
|
|
1897
|
+
onOffsetChange={this.paginate}
|
|
1898
|
+
pageSize={currentPageSize}
|
|
1899
|
+
totalCount={totalCount}
|
|
1900
|
+
onMarkerBasedPageChange={this.markerBasedPaginate}
|
|
1901
|
+
/>
|
|
1902
|
+
</Footer>
|
|
1903
|
+
)}
|
|
1904
|
+
</div>
|
|
1905
|
+
{isDefaultViewMetadata && isMetadataViewV2Feature && isMetadataSidePanelOpen && (
|
|
1906
|
+
<MetadataSidePanel
|
|
1907
|
+
currentCollection={currentCollection}
|
|
1908
|
+
metadataTemplate={metadataTemplate}
|
|
1909
|
+
onClose={this.closeMetadataSidePanel}
|
|
1910
|
+
onUpdate={this.updateMetadataV2}
|
|
1911
|
+
refreshCollection={this.refreshCollection}
|
|
1912
|
+
selectedItemIds={selectedItemIds}
|
|
1913
|
+
/>
|
|
1795
1914
|
)}
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
onCreate={this.createFolder}
|
|
1814
|
-
onGridViewSliderChange={this.onGridViewSliderChange}
|
|
1815
|
-
onItemClick={this.fetchFolder}
|
|
1816
|
-
onSortChange={this.sort}
|
|
1817
|
-
onMetadataSidePanelToggle={this.onMetadataSidePanelToggle}
|
|
1818
|
-
onViewModeChange={this.changeViewMode}
|
|
1819
|
-
portalElement={this.rootElement}
|
|
1820
|
-
selectedItemIds={selectedItemIds}
|
|
1821
|
-
title={title}
|
|
1915
|
+
</div>
|
|
1916
|
+
{allowUpload && !!this.appElement ? (
|
|
1917
|
+
<UploadDialog
|
|
1918
|
+
isOpen={isUploadModalOpen}
|
|
1919
|
+
currentFolderId={id}
|
|
1920
|
+
token={token}
|
|
1921
|
+
sharedLink={sharedLink}
|
|
1922
|
+
sharedLinkPassword={sharedLinkPassword}
|
|
1923
|
+
apiHost={apiHost}
|
|
1924
|
+
uploadHost={uploadHost}
|
|
1925
|
+
onClose={this.uploadSuccessHandler}
|
|
1926
|
+
parentElement={this.rootElement}
|
|
1927
|
+
appElement={this.appElement}
|
|
1928
|
+
onUpload={onUpload}
|
|
1929
|
+
contentUploaderProps={contentUploaderProps}
|
|
1930
|
+
requestInterceptor={requestInterceptor}
|
|
1931
|
+
responseInterceptor={responseInterceptor}
|
|
1822
1932
|
/>
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
isMedium={isMedium}
|
|
1834
|
-
isSmall={isSmall}
|
|
1835
|
-
isTouch={isTouch}
|
|
1836
|
-
itemActions={itemActions}
|
|
1837
|
-
fieldsToShow={fieldsToShow}
|
|
1838
|
-
metadataTemplate={metadataTemplate}
|
|
1839
|
-
metadataViewProps={metadataViewProps}
|
|
1840
|
-
onItemClick={this.onItemClick}
|
|
1841
|
-
onItemDelete={this.delete}
|
|
1842
|
-
onItemDownload={this.download}
|
|
1843
|
-
onItemPreview={this.preview}
|
|
1844
|
-
onItemRename={this.rename}
|
|
1845
|
-
onItemSelect={this.select}
|
|
1846
|
-
onItemShare={this.share}
|
|
1847
|
-
onMetadataUpdate={this.updateMetadata}
|
|
1848
|
-
onSortChange={this.sort}
|
|
1849
|
-
portalElement={this.rootElement}
|
|
1850
|
-
view={view}
|
|
1851
|
-
viewMode={viewMode}
|
|
1933
|
+
) : null}
|
|
1934
|
+
{allowCreate && !!this.appElement ? (
|
|
1935
|
+
<CreateFolderDialog
|
|
1936
|
+
isOpen={isCreateFolderModalOpen}
|
|
1937
|
+
onCreate={this.throttledCreateFolderCallback}
|
|
1938
|
+
onCancel={this.closeModals}
|
|
1939
|
+
isLoading={isLoading}
|
|
1940
|
+
errorCode={errorCode}
|
|
1941
|
+
parentElement={this.rootElement}
|
|
1942
|
+
appElement={this.appElement}
|
|
1852
1943
|
/>
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1944
|
+
) : null}
|
|
1945
|
+
{canDelete && selected && !!this.appElement ? (
|
|
1946
|
+
<DeleteConfirmationDialog
|
|
1947
|
+
isOpen={isDeleteModalOpen}
|
|
1948
|
+
onDelete={this.deleteCallback}
|
|
1949
|
+
onCancel={this.closeModals}
|
|
1950
|
+
item={selected}
|
|
1951
|
+
isLoading={isLoading}
|
|
1952
|
+
parentElement={this.rootElement}
|
|
1953
|
+
appElement={this.appElement}
|
|
1954
|
+
/>
|
|
1955
|
+
) : null}
|
|
1956
|
+
{canRename && selected && !!this.appElement ? (
|
|
1957
|
+
<RenameDialog
|
|
1958
|
+
isOpen={isRenameModalOpen}
|
|
1959
|
+
onRename={this.renameCallback}
|
|
1960
|
+
onCancel={this.closeModals}
|
|
1961
|
+
item={selected}
|
|
1962
|
+
isLoading={isLoading}
|
|
1963
|
+
errorCode={errorCode}
|
|
1964
|
+
parentElement={this.rootElement}
|
|
1965
|
+
appElement={this.appElement}
|
|
1966
|
+
/>
|
|
1967
|
+
) : null}
|
|
1968
|
+
{canShare && selected && !!this.appElement ? (
|
|
1969
|
+
<ShareDialog
|
|
1970
|
+
isOpen={isShareModalOpen}
|
|
1971
|
+
canSetShareAccess={canSetShareAccess}
|
|
1972
|
+
onShareAccessChange={this.changeShareAccess}
|
|
1973
|
+
onCancel={this.refreshCollection}
|
|
1974
|
+
item={selected}
|
|
1975
|
+
isLoading={isLoading}
|
|
1976
|
+
parentElement={this.rootElement}
|
|
1977
|
+
appElement={this.appElement}
|
|
1978
|
+
/>
|
|
1979
|
+
) : null}
|
|
1980
|
+
{canPreview && selected && !!this.appElement ? (
|
|
1981
|
+
<PreviewDialog
|
|
1982
|
+
isOpen={isPreviewModalOpen}
|
|
1983
|
+
isTouch={isTouch}
|
|
1984
|
+
onCancel={this.closeModals}
|
|
1985
|
+
item={selected}
|
|
1986
|
+
currentCollection={cloneDeep(currentCollection)}
|
|
1987
|
+
token={token}
|
|
1988
|
+
parentElement={this.rootElement}
|
|
1989
|
+
appElement={this.appElement}
|
|
1990
|
+
onPreview={onPreview}
|
|
1991
|
+
onDownload={onDownload}
|
|
1992
|
+
canDownload={canDownload}
|
|
1993
|
+
cache={this.api.getCache()}
|
|
1994
|
+
apiHost={apiHost}
|
|
1995
|
+
appHost={appHost}
|
|
1996
|
+
staticHost={staticHost}
|
|
1997
|
+
staticPath={staticPath}
|
|
1998
|
+
previewLibraryVersion={previewLibraryVersion}
|
|
1999
|
+
sharedLink={sharedLink}
|
|
2000
|
+
sharedLinkPassword={sharedLinkPassword}
|
|
2001
|
+
contentPreviewProps={contentPreviewProps}
|
|
2002
|
+
requestInterceptor={requestInterceptor}
|
|
2003
|
+
responseInterceptor={responseInterceptor}
|
|
1875
2004
|
/>
|
|
1876
|
-
)}
|
|
2005
|
+
) : null}
|
|
1877
2006
|
</div>
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
isOpen={isUploadModalOpen}
|
|
1881
|
-
currentFolderId={id}
|
|
1882
|
-
token={token}
|
|
1883
|
-
sharedLink={sharedLink}
|
|
1884
|
-
sharedLinkPassword={sharedLinkPassword}
|
|
1885
|
-
apiHost={apiHost}
|
|
1886
|
-
uploadHost={uploadHost}
|
|
1887
|
-
onClose={this.uploadSuccessHandler}
|
|
1888
|
-
parentElement={this.rootElement}
|
|
1889
|
-
appElement={this.appElement}
|
|
1890
|
-
onUpload={onUpload}
|
|
1891
|
-
contentUploaderProps={contentUploaderProps}
|
|
1892
|
-
requestInterceptor={requestInterceptor}
|
|
1893
|
-
responseInterceptor={responseInterceptor}
|
|
1894
|
-
/>
|
|
1895
|
-
) : null}
|
|
1896
|
-
{allowCreate && !!this.appElement ? (
|
|
1897
|
-
<CreateFolderDialog
|
|
1898
|
-
isOpen={isCreateFolderModalOpen}
|
|
1899
|
-
onCreate={this.throttledCreateFolderCallback}
|
|
1900
|
-
onCancel={this.closeModals}
|
|
1901
|
-
isLoading={isLoading}
|
|
1902
|
-
errorCode={errorCode}
|
|
1903
|
-
parentElement={this.rootElement}
|
|
1904
|
-
appElement={this.appElement}
|
|
1905
|
-
/>
|
|
1906
|
-
) : null}
|
|
1907
|
-
{canDelete && selected && !!this.appElement ? (
|
|
1908
|
-
<DeleteConfirmationDialog
|
|
1909
|
-
isOpen={isDeleteModalOpen}
|
|
1910
|
-
onDelete={this.deleteCallback}
|
|
1911
|
-
onCancel={this.closeModals}
|
|
1912
|
-
item={selected}
|
|
1913
|
-
isLoading={isLoading}
|
|
1914
|
-
parentElement={this.rootElement}
|
|
1915
|
-
appElement={this.appElement}
|
|
1916
|
-
/>
|
|
1917
|
-
) : null}
|
|
1918
|
-
{canRename && selected && !!this.appElement ? (
|
|
1919
|
-
<RenameDialog
|
|
1920
|
-
isOpen={isRenameModalOpen}
|
|
1921
|
-
onRename={this.renameCallback}
|
|
1922
|
-
onCancel={this.closeModals}
|
|
1923
|
-
item={selected}
|
|
1924
|
-
isLoading={isLoading}
|
|
1925
|
-
errorCode={errorCode}
|
|
1926
|
-
parentElement={this.rootElement}
|
|
1927
|
-
appElement={this.appElement}
|
|
1928
|
-
/>
|
|
1929
|
-
) : null}
|
|
1930
|
-
{canShare && selected && !!this.appElement ? (
|
|
1931
|
-
<ShareDialog
|
|
1932
|
-
isOpen={isShareModalOpen}
|
|
1933
|
-
canSetShareAccess={canSetShareAccess}
|
|
1934
|
-
onShareAccessChange={this.changeShareAccess}
|
|
1935
|
-
onCancel={this.refreshCollection}
|
|
1936
|
-
item={selected}
|
|
1937
|
-
isLoading={isLoading}
|
|
1938
|
-
parentElement={this.rootElement}
|
|
1939
|
-
appElement={this.appElement}
|
|
1940
|
-
/>
|
|
1941
|
-
) : null}
|
|
1942
|
-
{canPreview && selected && !!this.appElement ? (
|
|
1943
|
-
<PreviewDialog
|
|
1944
|
-
isOpen={isPreviewModalOpen}
|
|
1945
|
-
isTouch={isTouch}
|
|
1946
|
-
onCancel={this.closeModals}
|
|
1947
|
-
item={selected}
|
|
1948
|
-
currentCollection={cloneDeep(currentCollection)}
|
|
1949
|
-
token={token}
|
|
1950
|
-
parentElement={this.rootElement}
|
|
1951
|
-
appElement={this.appElement}
|
|
1952
|
-
onPreview={onPreview}
|
|
1953
|
-
onDownload={onDownload}
|
|
1954
|
-
canDownload={canDownload}
|
|
1955
|
-
cache={this.api.getCache()}
|
|
1956
|
-
apiHost={apiHost}
|
|
1957
|
-
appHost={appHost}
|
|
1958
|
-
staticHost={staticHost}
|
|
1959
|
-
staticPath={staticPath}
|
|
1960
|
-
previewLibraryVersion={previewLibraryVersion}
|
|
1961
|
-
sharedLink={sharedLink}
|
|
1962
|
-
sharedLinkPassword={sharedLinkPassword}
|
|
1963
|
-
contentPreviewProps={contentPreviewProps}
|
|
1964
|
-
requestInterceptor={requestInterceptor}
|
|
1965
|
-
responseInterceptor={responseInterceptor}
|
|
1966
|
-
/>
|
|
1967
|
-
) : null}
|
|
1968
|
-
</div>
|
|
1969
|
-
</TooltipProvider>
|
|
2007
|
+
</TooltipProvider>
|
|
2008
|
+
</Notification.Provider>
|
|
1970
2009
|
</Internationalize>
|
|
1971
2010
|
);
|
|
1972
2011
|
/* eslint-enable jsx-a11y/no-static-element-interactions */
|
|
@@ -3,8 +3,10 @@ import find from 'lodash/find';
|
|
|
3
3
|
import getProp from 'lodash/get';
|
|
4
4
|
import includes from 'lodash/includes';
|
|
5
5
|
import isArray from 'lodash/isArray';
|
|
6
|
-
import
|
|
6
|
+
import type { MetadataTemplateField } from '@box/metadata-editor';
|
|
7
|
+
import type { MetadataFieldType } from '@box/metadata-view';
|
|
7
8
|
import API from '../../api';
|
|
9
|
+
import { areFieldValuesEqual, isEmptyValue, isMultiValuesField } from './utils';
|
|
8
10
|
|
|
9
11
|
import {
|
|
10
12
|
JSON_PATCH_OP_ADD,
|
|
@@ -14,7 +16,7 @@ import {
|
|
|
14
16
|
METADATA_FIELD_TYPE_ENUM,
|
|
15
17
|
METADATA_FIELD_TYPE_MULTISELECT,
|
|
16
18
|
} from '../../common/constants';
|
|
17
|
-
import { FIELD_NAME, FIELD_METADATA, FIELD_EXTENSION } from '../../constants';
|
|
19
|
+
import { FIELD_NAME, FIELD_METADATA, FIELD_EXTENSION, FIELD_PERMISSIONS } from '../../constants';
|
|
18
20
|
|
|
19
21
|
import type { MetadataQuery as MetadataQueryType, MetadataQueryResponseData } from '../../common/types/metadataQueries';
|
|
20
22
|
import type {
|
|
@@ -57,13 +59,18 @@ export default class MetadataQueryAPIHelper {
|
|
|
57
59
|
oldValue: MetadataFieldValue | null,
|
|
58
60
|
newValue: MetadataFieldValue | null,
|
|
59
61
|
): JSONPatchOperations => {
|
|
62
|
+
// check if two values are the same, return empty operations if so
|
|
63
|
+
if (areFieldValuesEqual(oldValue, newValue)) {
|
|
64
|
+
return [];
|
|
65
|
+
}
|
|
66
|
+
|
|
60
67
|
let operation = JSON_PATCH_OP_REPLACE;
|
|
61
68
|
|
|
62
|
-
if (
|
|
69
|
+
if (isEmptyValue(oldValue) && !isEmptyValue(newValue)) {
|
|
63
70
|
operation = JSON_PATCH_OP_ADD;
|
|
64
71
|
}
|
|
65
72
|
|
|
66
|
-
if (oldValue &&
|
|
73
|
+
if (!isEmptyValue(oldValue) && isEmptyValue(newValue)) {
|
|
67
74
|
operation = JSON_PATCH_OP_REMOVE;
|
|
68
75
|
}
|
|
69
76
|
|
|
@@ -170,6 +177,51 @@ export default class MetadataQueryAPIHelper {
|
|
|
170
177
|
return this.api.getMetadataAPI(true).getSchemaByTemplateKey(this.templateKey);
|
|
171
178
|
};
|
|
172
179
|
|
|
180
|
+
/**
|
|
181
|
+
* Generate operations for all fields update in the metadata sidepanel
|
|
182
|
+
*
|
|
183
|
+
* @private
|
|
184
|
+
* @return {JSONPatchOperations}
|
|
185
|
+
*/
|
|
186
|
+
generateOperations = (
|
|
187
|
+
item: BoxItem,
|
|
188
|
+
templateOldFields: MetadataTemplateField[],
|
|
189
|
+
templateNewFields: MetadataTemplateField[],
|
|
190
|
+
): JSONPatchOperations => {
|
|
191
|
+
const { scope, templateKey } = this.metadataTemplate;
|
|
192
|
+
const itemFields = item.metadata[scope][templateKey];
|
|
193
|
+
const operations = templateNewFields.flatMap(newField => {
|
|
194
|
+
let newFieldValue = newField.value;
|
|
195
|
+
const { key, type } = newField;
|
|
196
|
+
// when retrieve value from float type field, it gives a string instead
|
|
197
|
+
if (type === 'float' && newFieldValue !== '') {
|
|
198
|
+
newFieldValue = Number(newFieldValue);
|
|
199
|
+
}
|
|
200
|
+
const oldField = templateOldFields.find(f => f.key === key);
|
|
201
|
+
const oldFieldValue = oldField.value;
|
|
202
|
+
|
|
203
|
+
/*
|
|
204
|
+
Generate operations array based on all the fields' orignal value and the incoming updated value.
|
|
205
|
+
|
|
206
|
+
Edge Case:
|
|
207
|
+
If there are multiple items shared different value for enum or multi-select field, the form will
|
|
208
|
+
return 'Multiple values' as the value. In this case, it needs to generate operation based on the
|
|
209
|
+
actual item's field value.
|
|
210
|
+
*/
|
|
211
|
+
const shouldUseItemFieldValue =
|
|
212
|
+
isMultiValuesField(type as MetadataFieldType, oldFieldValue) &&
|
|
213
|
+
!isMultiValuesField(type as MetadataFieldType, newFieldValue);
|
|
214
|
+
|
|
215
|
+
return this.createJSONPatchOperations(
|
|
216
|
+
key,
|
|
217
|
+
shouldUseItemFieldValue ? itemFields[key] : oldFieldValue,
|
|
218
|
+
newFieldValue,
|
|
219
|
+
);
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
return operations;
|
|
223
|
+
};
|
|
224
|
+
|
|
173
225
|
queryMetadata = (): Promise<MetadataQueryResponseData> => {
|
|
174
226
|
return new Promise((resolve, reject) => {
|
|
175
227
|
this.api.getMetadataQueryAPI().queryMetadata(this.metadataQuery, resolve, reject, { forceFetch: true });
|
|
@@ -205,6 +257,34 @@ export default class MetadataQueryAPIHelper {
|
|
|
205
257
|
.updateMetadata(file, this.metadataTemplate, operations, successCallback, errorCallback);
|
|
206
258
|
};
|
|
207
259
|
|
|
260
|
+
updateMetadataWithOperations = (
|
|
261
|
+
item: BoxItem,
|
|
262
|
+
operations: JSONPatchOperations,
|
|
263
|
+
successCallback: () => void,
|
|
264
|
+
errorCallback: ErrorCallback,
|
|
265
|
+
): Promise<void> => {
|
|
266
|
+
return this.api
|
|
267
|
+
.getMetadataAPI(true)
|
|
268
|
+
.updateMetadata(item, this.metadataTemplate, operations, successCallback, errorCallback);
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
bulkUpdateMetadata = (
|
|
272
|
+
items: BoxItem[],
|
|
273
|
+
templateOldFields: MetadataTemplateField[],
|
|
274
|
+
templateNewFields: MetadataTemplateField[],
|
|
275
|
+
successCallback: () => void,
|
|
276
|
+
errorCallback: ErrorCallback,
|
|
277
|
+
): Promise<void> => {
|
|
278
|
+
const operations: JSONPatchOperations = [];
|
|
279
|
+
items.forEach(item => {
|
|
280
|
+
const operation = this.generateOperations(item, templateOldFields, templateNewFields);
|
|
281
|
+
operations.push(operation);
|
|
282
|
+
});
|
|
283
|
+
return this.api
|
|
284
|
+
.getMetadataAPI(true)
|
|
285
|
+
.bulkUpdateMetadata(items, this.metadataTemplate, operations, successCallback, errorCallback);
|
|
286
|
+
};
|
|
287
|
+
|
|
208
288
|
/**
|
|
209
289
|
* Verify that the metadata query has required fields and update it if necessary
|
|
210
290
|
* For a file item, default fields included in the response are "type", "id", "etag"
|
|
@@ -225,6 +305,11 @@ export default class MetadataQueryAPIHelper {
|
|
|
225
305
|
clonedFields.push(FIELD_EXTENSION);
|
|
226
306
|
}
|
|
227
307
|
|
|
308
|
+
// This field is necessary to check if the user has permission to update metadata
|
|
309
|
+
if (!clonedFields.includes(FIELD_PERMISSIONS)) {
|
|
310
|
+
clonedFields.push(FIELD_PERMISSIONS);
|
|
311
|
+
}
|
|
312
|
+
|
|
228
313
|
clonedQuery.fields = clonedFields;
|
|
229
314
|
|
|
230
315
|
return clonedQuery;
|