metadata-based-explorer1
Version:
Box UI Elements
1,520 lines (1,258 loc) • 51.5 kB
JavaScript
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
/**
*
* @file Content Explorer Component
* @author Box
*/
import 'regenerator-runtime/runtime';
import React, { Component } from 'react';
import classNames from 'classnames';
import cloneDeep from 'lodash/cloneDeep';
import debounce from 'lodash/debounce';
import flow from 'lodash/flow';
import noop from 'lodash/noop';
import uniqueid from 'lodash/uniqueId';
import CreateFolderDialog from '../common/create-folder-dialog';
import UploadDialog from '../common/upload-dialog';
import Header from '../common/header';
import Pagination from '../common/pagination';
import SubHeader from '../common/sub-header/SubHeader';
import makeResponsive from '../common/makeResponsive';
import openUrlInsideIframe from '../../utils/iframe';
import Internationalize from '../common/Internationalize';
import API from '../../api';
import Footer from './Footer';
import PreviewDialog from './PreviewDialog';
import ShareDialog from './ShareDialog';
import RenameDialog from './RenameDialog';
import DeleteConfirmationDialog from './DeleteConfirmationDialog';
import Content from './Content';
import { isFocusableElement, isInputElement, focus } from '../../utils/dom';
import { FILE_SHARED_LINK_FIELDS_TO_FETCH, FOLDER_FIELDS_TO_FETCH } from '../../utils/fields';
import LocalStore from '../../utils/LocalStore';
import { isFeatureEnabled, withFeatureConsumer, withFeatureProvider } from '../common/feature-checking';
import { DEFAULT_HOSTNAME_UPLOAD, DEFAULT_HOSTNAME_API, DEFAULT_HOSTNAME_APP, DEFAULT_HOSTNAME_STATIC, DEFAULT_SEARCH_DEBOUNCE, SORT_ASC, FIELD_NAME, FIELD_REPRESENTATIONS, DEFAULT_ROOT, VIEW_SEARCH, VIEW_FOLDER, VIEW_ERROR, VIEW_RECENTS, VIEW_MODE_LIST, VIEW_MODE_METADATA_BASED_LIST, TYPE_FILE, TYPE_WEBLINK, TYPE_FOLDER, CLIENT_NAME_CONTENT_EXPLORER, DEFAULT_PAGE_NUMBER, DEFAULT_PAGE_SIZE, DEFAULT_VIEW_FILES, DEFAULT_VIEW_RECENTS, DEFAULT_VIEW_METADATA, ERROR_CODE_ITEM_NAME_INVALID, ERROR_CODE_ITEM_NAME_TOO_LONG, TYPED_ID_FOLDER_PREFIX } from '../../constants';
import '../common/fonts.scss';
import '../common/base.scss';
import '../common/modal.scss';
import './ContentExplorer.scss';
var GRID_VIEW_MAX_COLUMNS = 7;
var GRID_VIEW_MIN_COLUMNS = 1;
var localStoreViewMode = 'bce.defaultViewMode';
var ContentExplorer =
/*#__PURE__*/
function (_Component) {
_inherits(ContentExplorer, _Component);
// Keeps track of very 1st load
/**
* [constructor]
*
* @private
* @return {ContentExplorer}
*/
function ContentExplorer(props) {
var _this;
_classCallCheck(this, ContentExplorer);
_this = _possibleConstructorReturn(this, _getPrototypeOf(ContentExplorer).call(this, props));
_defineProperty(_assertThisInitialized(_this), "firstLoad", true);
_defineProperty(_assertThisInitialized(_this), "store", new LocalStore());
_defineProperty(_assertThisInitialized(_this), "errorCallback", function (error) {
_this.setState({
view: VIEW_ERROR
});
/* eslint-disable no-console */
console.error(error);
/* eslint-enable no-console */
});
_defineProperty(_assertThisInitialized(_this), "refreshCollection", function () {
var _this$state = _this.state,
id = _this$state.currentCollection.id,
view = _this$state.view,
searchQuery = _this$state.searchQuery;
if (view === VIEW_FOLDER && id) {
_this.fetchFolder(id, false);
} else if (view === VIEW_RECENTS) {
_this.showRecents(false);
} else if (view === VIEW_SEARCH && searchQuery) {
_this.search(searchQuery);
} else {
throw new Error('Cannot refresh incompatible view!');
}
});
_defineProperty(_assertThisInitialized(_this), "getFolderFields", function () {
var features = _this.props.features;
return isFeatureEnabled(features, 'contentExplorer.gridView.enabled') ? [].concat(_toConsumableArray(FOLDER_FIELDS_TO_FETCH), [FIELD_REPRESENTATIONS]) : FOLDER_FIELDS_TO_FETCH;
});
_defineProperty(_assertThisInitialized(_this), "fetchFolder", function (id) {
var triggerNavigationEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;
var rootFolderId = _this.props.rootFolderId;
var _this$state2 = _this.state,
currentId = _this$state2.currentCollection.id,
currentOffset = _this$state2.currentOffset,
limit = _this$state2.currentPageSize,
_this$state2$searchQu = _this$state2.searchQuery,
searchQuery = _this$state2$searchQu === void 0 ? '' : _this$state2$searchQu,
sortBy = _this$state2.sortBy,
sortDirection = _this$state2.sortDirection;
var folderId = typeof id === 'string' ? id : rootFolderId;
var hasFolderChanged = currentId && currentId !== folderId;
var hasSearchQuery = !!searchQuery.trim().length;
var offset = hasFolderChanged || hasSearchQuery ? 0 : currentOffset; // Reset offset on folder or mode change
// If we are navigating around, aka not first load
// then reset the focus to the root so that after
// the collection loads the activeElement is not the
// button that was clicked to fetch the folder
if (!_this.firstLoad) {
_this.rootElement.focus();
} // Reset search state, the view and show busy indicator
_this.setState({
searchQuery: '',
view: VIEW_FOLDER,
currentCollection: _this.currentUnloadedCollection(),
currentOffset: offset
}); // Fetch the folder using folder API
_this.api.getFolderAPI().getFolder(folderId, limit, offset, sortBy, sortDirection, function (collection) {
_this.fetchFolderSuccessCallback(collection, triggerNavigationEvent);
}, _this.errorCallback, {
fields: _this.getFolderFields(),
forceFetch: true
});
});
_defineProperty(_assertThisInitialized(_this), "onItemClick", function (item) {
// If the id was passed in, just use that
if (typeof item === 'string') {
_this.fetchFolder(item);
return;
}
var id = item.id,
type = item.type;
var isTouch = _this.props.isTouch;
if (type === TYPE_FOLDER) {
_this.fetchFolder(id);
return;
}
if (isTouch) {
return;
}
_this.preview(item);
});
_defineProperty(_assertThisInitialized(_this), "searchSuccessCallback", function (collection) {
var selected = _this.state.selected; // Close any open modals
_this.closeModals();
_this.updateCollection(collection, selected);
});
_defineProperty(_assertThisInitialized(_this), "debouncedSearch", debounce(function (id, query) {
var _this$state3 = _this.state,
currentOffset = _this$state3.currentOffset,
currentPageSize = _this$state3.currentPageSize;
_this.api.getSearchAPI().search(id, query, currentPageSize, currentOffset, _this.searchSuccessCallback, _this.errorCallback, {
fields: _this.getFolderFields(),
forceFetch: true
});
}, DEFAULT_SEARCH_DEBOUNCE));
_defineProperty(_assertThisInitialized(_this), "search", function (query) {
var rootFolderId = _this.props.rootFolderId;
var _this$state4 = _this.state,
id = _this$state4.currentCollection.id,
currentOffset = _this$state4.currentOffset,
searchQuery = _this$state4.searchQuery;
var folderId = typeof id === 'string' ? id : rootFolderId;
var trimmedQuery = query.trim();
if (!query) {
// Cancel the debounce so we don't search on a previous query
_this.debouncedSearch.cancel(); // Query was cleared out, load the prior folder
// The prior folder is always the parent folder for search
_this.setState({
currentOffset: 0
}, function () {
_this.fetchFolder(folderId, false);
});
return;
}
if (!trimmedQuery) {
// Query now only has bunch of spaces
// do nothing and but update prior state
_this.setState({
searchQuery: query
});
return;
}
_this.setState({
currentCollection: _this.currentUnloadedCollection(),
currentOffset: trimmedQuery === searchQuery ? currentOffset : 0,
searchQuery: query,
selected: undefined,
view: VIEW_SEARCH
});
_this.debouncedSearch(folderId, query);
});
_defineProperty(_assertThisInitialized(_this), "upload", function () {
var _this$state$currentCo = _this.state.currentCollection,
id = _this$state$currentCo.id,
permissions = _this$state$currentCo.permissions;
var canUpload = _this.props.canUpload;
if (!canUpload || !id || !permissions) {
return;
}
var can_upload = permissions.can_upload;
if (!can_upload) {
return;
}
_this.setState({
isUploadModalOpen: true
});
});
_defineProperty(_assertThisInitialized(_this), "uploadSuccessHandler", function () {
var id = _this.state.currentCollection.id;
_this.fetchFolder(id, false);
});
_defineProperty(_assertThisInitialized(_this), "changeShareAccess", function (access) {
var selected = _this.state.selected;
var canSetShareAccess = _this.props.canSetShareAccess;
if (!selected || !canSetShareAccess) {
return;
}
var permissions = selected.permissions,
type = selected.type;
if (!permissions || !type) {
return;
}
var can_set_share_access = permissions.can_set_share_access;
if (!can_set_share_access) {
return;
}
_this.setState({
isLoading: true
});
_this.api.getAPI(type).share(selected, access, function (updatedItem) {
_this.setState({
isLoading: false
});
_this.select(updatedItem);
});
});
_defineProperty(_assertThisInitialized(_this), "sort", function (sortBy, sortDirection) {
var id = _this.state.currentCollection.id;
if (id) {
_this.setState({
sortBy: sortBy,
sortDirection: sortDirection
}, _this.refreshCollection);
}
});
_defineProperty(_assertThisInitialized(_this), "select", function (item) {
var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : noop;
var _this$state5 = _this.state,
selected = _this$state5.selected,
currentCollection = _this$state5.currentCollection;
var _currentCollection$it = currentCollection.items,
items = _currentCollection$it === void 0 ? [] : _currentCollection$it;
var onSelect = _this.props.onSelect;
if (item === selected) {
callback(item);
return;
}
var selectedItem = _objectSpread({}, item, {
selected: true
});
_this.updateCollection(currentCollection, selectedItem, function () {
onSelect(cloneDeep([selectedItem]));
callback(selectedItem);
});
var focusedRow = items.findIndex(function (i) {
return i.id === item.id;
});
_this.setState({
focusedRow: focusedRow
});
});
_defineProperty(_assertThisInitialized(_this), "preview", function (item) {
var type = item.type,
url = item.url;
if (type === TYPE_WEBLINK) {
window.open(url);
return;
}
_this.select(item, _this.previewCallback);
});
_defineProperty(_assertThisInitialized(_this), "previewCallback", function () {
var selected = _this.state.selected;
var canPreview = _this.props.canPreview;
if (!selected || !canPreview) {
return;
}
var permissions = selected.permissions;
if (!permissions) {
return;
}
var can_preview = permissions.can_preview;
if (!can_preview) {
return;
}
_this.setState({
isPreviewModalOpen: true
});
});
_defineProperty(_assertThisInitialized(_this), "download", function (item) {
_this.select(item, _this.downloadCallback);
});
_defineProperty(_assertThisInitialized(_this), "downloadCallback", function () {
var selected = _this.state.selected;
var _this$props = _this.props,
canDownload = _this$props.canDownload,
onDownload = _this$props.onDownload;
if (!selected || !canDownload) {
return;
}
var id = selected.id,
permissions = selected.permissions;
if (!id || !permissions) {
return;
}
var can_download = permissions.can_download;
if (!can_download) {
return;
}
var openUrl = function openUrl(url) {
openUrlInsideIframe(url);
onDownload(cloneDeep([selected]));
};
var type = selected.type;
if (type === TYPE_FILE) {
_this.api.getFileAPI().getDownloadUrl(id, selected, openUrl, noop);
}
});
_defineProperty(_assertThisInitialized(_this), "delete", function (item) {
_this.select(item, _this.deleteCallback);
});
_defineProperty(_assertThisInitialized(_this), "deleteCallback", function () {
var _this$state6 = _this.state,
selected = _this$state6.selected,
isDeleteModalOpen = _this$state6.isDeleteModalOpen;
var _this$props2 = _this.props,
canDelete = _this$props2.canDelete,
onDelete = _this$props2.onDelete;
if (!selected || !canDelete) {
return;
}
var id = selected.id,
permissions = selected.permissions,
parent = selected.parent,
type = selected.type;
if (!id || !permissions || !parent || !type) {
return;
}
var parentId = parent.id;
var can_delete = permissions.can_delete;
if (!can_delete || !parentId) {
return;
}
if (!isDeleteModalOpen) {
_this.setState({
isDeleteModalOpen: true
});
return;
}
_this.setState({
isLoading: true
});
_this.api.getAPI(type).deleteItem(selected, function () {
onDelete(cloneDeep([selected]));
_this.refreshCollection();
});
});
_defineProperty(_assertThisInitialized(_this), "rename", function (item) {
_this.select(item, _this.renameCallback);
});
_defineProperty(_assertThisInitialized(_this), "renameCallback", function (nameWithoutExt, extension) {
var _this$state7 = _this.state,
selected = _this$state7.selected,
isRenameModalOpen = _this$state7.isRenameModalOpen;
var _this$props3 = _this.props,
canRename = _this$props3.canRename,
onRename = _this$props3.onRename;
if (!selected || !canRename) {
return;
}
var id = selected.id,
permissions = selected.permissions,
type = selected.type;
if (!id || !permissions || !type) {
return;
}
var can_rename = permissions.can_rename;
if (!can_rename) {
return;
}
if (!isRenameModalOpen || !nameWithoutExt) {
_this.setState({
isRenameModalOpen: true,
errorCode: ''
});
return;
}
var name = "".concat(nameWithoutExt).concat(extension);
if (!nameWithoutExt.trim()) {
_this.setState({
errorCode: ERROR_CODE_ITEM_NAME_INVALID,
isLoading: false
});
return;
}
_this.setState({
isLoading: true
});
_this.api.getAPI(type).rename(selected, name, function (updatedItem) {
_this.setState({
isRenameModalOpen: false
});
_this.refreshCollection();
_this.select(updatedItem);
onRename(cloneDeep(selected));
}, function (_ref) {
var code = _ref.code;
_this.setState({
errorCode: code,
isLoading: false
});
});
});
_defineProperty(_assertThisInitialized(_this), "createFolder", function () {
_this.createFolderCallback();
});
_defineProperty(_assertThisInitialized(_this), "createFolderCallback", function (name) {
var _this$state8 = _this.state,
isCreateFolderModalOpen = _this$state8.isCreateFolderModalOpen,
currentCollection = _this$state8.currentCollection;
var _this$props4 = _this.props,
canCreateNewFolder = _this$props4.canCreateNewFolder,
onCreate = _this$props4.onCreate;
if (!canCreateNewFolder) {
return;
}
var id = currentCollection.id,
permissions = currentCollection.permissions;
if (!id || !permissions) {
return;
}
var can_upload = permissions.can_upload;
if (!can_upload) {
return;
}
if (!isCreateFolderModalOpen || !name) {
_this.setState({
isCreateFolderModalOpen: true,
errorCode: ''
});
return;
}
if (!name) {
_this.setState({
errorCode: ERROR_CODE_ITEM_NAME_INVALID,
isLoading: false
});
return;
}
if (name.length > 255) {
_this.setState({
errorCode: ERROR_CODE_ITEM_NAME_TOO_LONG,
isLoading: false
});
return;
}
_this.setState({
isLoading: true
});
_this.api.getFolderAPI().create(id, name, function (item) {
_this.refreshCollection();
_this.select(item);
onCreate(cloneDeep(item));
}, function (_ref2) {
var code = _ref2.code;
_this.setState({
errorCode: code,
isLoading: false
});
});
});
_defineProperty(_assertThisInitialized(_this), "share", function (item) {
_this.select(item, _this.shareCallback);
});
_defineProperty(_assertThisInitialized(_this), "fetchSharedLinkInfo", function (item) {
var id = item.id,
type = item.type;
switch (type) {
case TYPE_FOLDER:
_this.api.getFolderAPI().getFolderFields(id, _this.handleSharedLinkSuccess, noop, {
fields: FILE_SHARED_LINK_FIELDS_TO_FETCH
});
break;
case TYPE_FILE:
_this.api.getFileAPI().getFile(id, _this.handleSharedLinkSuccess, noop, {
fields: FILE_SHARED_LINK_FIELDS_TO_FETCH
});
break;
case TYPE_WEBLINK:
_this.api.getWebLinkAPI().getWeblink(id, _this.handleSharedLinkSuccess, noop, {
fields: FILE_SHARED_LINK_FIELDS_TO_FETCH
});
break;
default:
throw new Error('Unknown Type');
}
});
_defineProperty(_assertThisInitialized(_this), "handleSharedLinkSuccess", function (newItem) {
var currentCollection = _this.state.currentCollection; // Update item in collection
_this.updateCollection(currentCollection, newItem, function () {
return _this.setState({
isShareModalOpen: true
});
});
});
_defineProperty(_assertThisInitialized(_this), "shareCallback", function () {
var selected = _this.state.selected;
var canShare = _this.props.canShare;
if (!selected || !canShare) {
return;
}
var permissions = selected.permissions;
if (!permissions) {
return;
}
var can_share = permissions.can_share;
if (!can_share) {
return;
}
_this.fetchSharedLinkInfo(selected);
});
_defineProperty(_assertThisInitialized(_this), "tableRef", function (table) {
_this.table = table;
});
_defineProperty(_assertThisInitialized(_this), "closeModals", function () {
var focusedRow = _this.state.focusedRow;
_this.setState({
isLoading: false,
isDeleteModalOpen: false,
isRenameModalOpen: false,
isCreateFolderModalOpen: false,
isShareModalOpen: false,
isUploadModalOpen: false,
isPreviewModalOpen: false
});
var _this$state9 = _this.state,
selected = _this$state9.selected,
_this$state9$currentC = _this$state9.currentCollection.items,
items = _this$state9$currentC === void 0 ? [] : _this$state9$currentC;
if (selected && items.length > 0) {
focus(_this.rootElement, ".bce-item-row-".concat(focusedRow));
}
});
_defineProperty(_assertThisInitialized(_this), "onKeyDown", function (event) {
if (isInputElement(event.target)) {
return;
}
var rootFolderId = _this.props.rootFolderId;
var key = event.key.toLowerCase();
switch (key) {
case '/':
focus(_this.rootElement, '.be-search input[type="search"]', false);
event.preventDefault();
break;
case 'arrowdown':
focus(_this.rootElement, '.bce-item-row', false);
_this.setState({
focusedRow: 0
});
event.preventDefault();
break;
case 'g':
break;
case 'b':
if (_this.globalModifier) {
focus(_this.rootElement, '.be-breadcrumb button', false);
event.preventDefault();
}
break;
case 'f':
if (_this.globalModifier) {
_this.fetchFolder(rootFolderId);
event.preventDefault();
}
break;
case 'u':
if (_this.globalModifier) {
_this.upload();
event.preventDefault();
}
break;
case 'r':
if (_this.globalModifier) {
_this.showRecents();
event.preventDefault();
}
break;
case 'n':
if (_this.globalModifier) {
_this.createFolder();
event.preventDefault();
}
break;
default:
_this.globalModifier = false;
return;
}
_this.globalModifier = key === 'g';
});
_defineProperty(_assertThisInitialized(_this), "paginate", function (newOffset) {
_this.setState({
currentOffset: newOffset
}, _this.refreshCollection);
});
_defineProperty(_assertThisInitialized(_this), "getViewMode", function () {
var _this$props5 = _this.props,
features = _this$props5.features,
defaultView = _this$props5.defaultView;
if (defaultView === DEFAULT_VIEW_METADATA) {
return VIEW_MODE_METADATA_BASED_LIST;
}
var viewModePreference = _this.store.getItem(localStoreViewMode);
var isGridViewEnabled = isFeatureEnabled(features, 'contentExplorer.gridView.enabled');
return isGridViewEnabled && viewModePreference ? viewModePreference : VIEW_MODE_LIST;
});
_defineProperty(_assertThisInitialized(_this), "getMaxNumberOfGridViewColumnsForWidth", function () {
var _this$props6 = _this.props,
isSmall = _this$props6.isSmall,
isMedium = _this$props6.isMedium,
isLarge = _this$props6.isLarge;
var maxWidthColumns = GRID_VIEW_MAX_COLUMNS;
if (isSmall) {
maxWidthColumns = 1;
} else if (isMedium) {
maxWidthColumns = 3;
} else if (isLarge) {
maxWidthColumns = 5;
}
return maxWidthColumns;
});
_defineProperty(_assertThisInitialized(_this), "changeViewMode", function (viewMode) {
var features = _this.props.features;
if (isFeatureEnabled(features, 'contentExplorer.gridView.enabled')) {
_this.store.setItem(localStoreViewMode, viewMode);
_this.forceUpdate();
}
});
_defineProperty(_assertThisInitialized(_this), "onGridViewSliderChange", function (sliderValue) {
// need to do this calculation since lowest value of grid view slider
// means highest number of columns
var gridColumnCount = GRID_VIEW_MAX_COLUMNS - sliderValue + 1;
_this.setState({
gridColumnCount: gridColumnCount
});
});
var apiHost = props.apiHost,
initialPage = props.initialPage,
initialPageSize = props.initialPageSize,
language = props.language,
requestInterceptor = props.requestInterceptor,
responseInterceptor = props.responseInterceptor,
_rootFolderId = props.rootFolderId,
sharedLink = props.sharedLink,
sharedLinkPassword = props.sharedLinkPassword,
_sortBy = props.sortBy,
_sortDirection = props.sortDirection,
token = props.token,
uploadHost = props.uploadHost;
_this.api = new API({
apiHost: apiHost,
clientName: CLIENT_NAME_CONTENT_EXPLORER,
id: "".concat(TYPED_ID_FOLDER_PREFIX).concat(_rootFolderId),
language: language,
requestInterceptor: requestInterceptor,
responseInterceptor: responseInterceptor,
sharedLink: sharedLink,
sharedLinkPassword: sharedLinkPassword,
token: token,
uploadHost: uploadHost
});
_this.id = uniqueid('bce_');
_this.state = {
currentCollection: {},
currentOffset: initialPageSize * (initialPage - 1),
currentPageSize: initialPageSize,
errorCode: '',
focusedRow: 0,
gridColumnCount: 4,
isCreateFolderModalOpen: false,
isDeleteModalOpen: false,
isLoading: false,
isPreviewModalOpen: false,
isRenameModalOpen: false,
isShareModalOpen: false,
isUploadModalOpen: false,
rootName: '',
searchQuery: '',
sortBy: _sortBy,
sortDirection: _sortDirection,
view: VIEW_FOLDER
};
return _this;
}
/**
* Destroys api instances
*
* @private
* @return {void}
*/
_createClass(ContentExplorer, [{
key: "clearCache",
value: function clearCache() {
this.api.destroy(true);
}
/**
* Cleanup
*
* @private
* @inheritdoc
* @return {void}
*/
}, {
key: "componentWillUnmount",
value: function componentWillUnmount() {
this.clearCache();
}
/**
* Fetches the root folder on load
*
* @private
* @inheritdoc
* @return {void}
*/
}, {
key: "componentDidMount",
value: function componentDidMount() {
var _this$props7 = this.props,
currentFolderId = _this$props7.currentFolderId,
defaultView = _this$props7.defaultView;
this.rootElement = document.getElementById(this.id);
this.appElement = this.rootElement.firstElementChild;
switch (defaultView) {
case DEFAULT_VIEW_RECENTS:
this.showRecents();
break;
case DEFAULT_VIEW_METADATA:
this.fetchMetadataQueryResults();
break;
default:
this.fetchFolder(currentFolderId);
}
}
/**
* Fetches the current folder if different
* from what was already fetched before.
*
* @private
* @inheritdoc
* @return {void}
*/
}, {
key: "componentWillReceiveProps",
value: function componentWillReceiveProps(nextProps) {
var currentFolderId = nextProps.currentFolderId;
var id = this.state.currentCollection.id;
if (typeof currentFolderId === 'string' && id !== currentFolderId) {
this.fetchFolder(currentFolderId);
}
}
/**
* Metadata queries success callback
*
* @private
* @param {Object} data - item collection object
* @return {void}
*/
}, {
key: "fetchMetadataQueryResultsSuccessCallback",
value: function fetchMetadataQueryResultsSuccessCallback(data) {
var currentCollection = this.state.currentCollection;
this.setState({
currentCollection: _extends({}, currentCollection, data, {
percentLoaded: 100
})
});
}
/**
* Queries metadata_queries/execute API and fetches the result
*
* @private
* @return {void}
*/
}, {
key: "fetchMetadataQueryResults",
value: function fetchMetadataQueryResults() {
var _this2 = this;
var metadataQuery = this.props.metadataQuery; // Reset search state, the view and show busy indicator
this.setState({
searchQuery: '',
currentCollection: this.currentUnloadedCollection()
}); // Fetch the Metadata Query Results
this.api.getMetadataQueryAPI().queryMetadata(metadataQuery, function (data) {
_this2.fetchMetadataQueryResultsSuccessCallback(data);
}, this.errorCallback, {
forceFetch: true
});
}
/**
* Resets the collection so that the loading bar starts showing
*
* @private
* @return {Collection}
*/
}, {
key: "currentUnloadedCollection",
value: function currentUnloadedCollection() {
var currentCollection = this.state.currentCollection;
return _extends(currentCollection, {
percentLoaded: 0
});
}
/**
* Network error callback
*
* @private
* @param {Error} error error object
* @return {void}
*/
}, {
key: "finishNavigation",
/**
* Focuses the grid and fires navigate event
*
* @private
* @return {void}
*/
value: function finishNavigation() {
var autoFocus = this.props.autoFocus;
var percentLoaded = this.state.currentCollection.percentLoaded; // If loading for the very first time, only allow focus if autoFocus is true
if (this.firstLoad && !autoFocus) {
this.firstLoad = false;
return;
} // Don't focus the grid until its loaded and user is not already on an interactable element
if (percentLoaded === 100 && !isFocusableElement(document.activeElement)) {
focus(this.rootElement, '.bce-item-row');
this.setState({
focusedRow: 0
});
}
this.firstLoad = false;
}
/**
* Refreshing the item collection depending upon the view.
* Navigation event is prevented.
*
* @private
* @return {void}
*/
}, {
key: "fetchFolderSuccessCallback",
/**
* Folder fetch success callback
*
* @private
* @param {Object} collection - item collection object
* @param {Boolean|void} triggerNavigationEvent - To trigger navigate event and focus grid
* @return {void}
*/
value: function fetchFolderSuccessCallback(collection, triggerNavigationEvent) {
var _this3 = this;
var _this$props8 = this.props,
onNavigate = _this$props8.onNavigate,
rootFolderId = _this$props8.rootFolderId;
var boxItem = collection.boxItem,
id = collection.id,
name = collection.name;
var selected = this.state.selected;
var rootName = id === rootFolderId ? name : ''; // Close any open modals
this.closeModals();
this.updateCollection(collection, selected, function () {
if (triggerNavigationEvent) {
// Fire folder navigation event
_this3.setState({
rootName: rootName
}, _this3.finishNavigation);
if (boxItem) {
onNavigate(cloneDeep(boxItem));
}
} else {
_this3.setState({
rootName: rootName
});
}
});
}
/**
* Fetches a folder, defaults to fetching root folder
*
* @private
* @param {string|void} [id] folder id
* @param {Boolean|void} [triggerNavigationEvent] To trigger navigate event
* @return {void}
*/
}, {
key: "recentsSuccessCallback",
/**
* Recents fetch success callback
*
* @private
* @param {Object} collection item collection object
* @param {Boolean} triggerNavigationEvent - To trigger navigate event
* @return {void}
*/
value: function recentsSuccessCallback(collection, triggerNavigationEvent) {
if (triggerNavigationEvent) {
this.updateCollection(collection, undefined, this.finishNavigation);
} else {
this.updateCollection(collection);
}
}
/**
* Shows recents.
*
* @private
* @param {Boolean|void} [triggerNavigationEvent] To trigger navigate event
* @return {void}
*/
}, {
key: "showRecents",
value: function showRecents() {
var _this4 = this;
var triggerNavigationEvent = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
var rootFolderId = this.props.rootFolderId; // Reset search state, the view and show busy indicator
this.setState({
searchQuery: '',
view: VIEW_RECENTS,
currentCollection: this.currentUnloadedCollection(),
currentOffset: 0
}); // Fetch the folder using folder API
this.api.getRecentsAPI().recents(rootFolderId, function (collection) {
_this4.recentsSuccessCallback(collection, triggerNavigationEvent);
}, this.errorCallback, {
fields: this.getFolderFields(),
forceFetch: true
});
}
/**
* Uploads
*
* @private
* @param {File} file dom file object
* @return {void}
*/
}, {
key: "updateCollection",
/**
* Sets state with currentCollection updated to have items.selected properties
* set according to the given selected param. Also updates the selected item in the
* currentcollection. selectedItem will be set to the selected state
* item if it is in currentCollection, otherwise it will be set to undefined.
*
* @private
* @param {Collection} collection - collection that needs to be updated
* @param {Object} [selectedItem] - The item that should be selected in that collection (if present)
* @param {Function} [callback] - callback function that should be called after setState occurs
* @return {void}
*/
value: function () {
var _updateCollection = _asyncToGenerator(
/*#__PURE__*/
regeneratorRuntime.mark(function _callee(collection, selectedItem) {
var callback,
features,
_collection$items,
items,
newCollection,
selectedId,
newSelectedItem,
isGridViewEnabled,
itemThumbnails,
fileAPI,
_args = arguments;
return regeneratorRuntime.wrap(function _callee$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
callback = _args.length > 2 && _args[2] !== undefined ? _args[2] : noop;
features = this.props.features;
_collection$items = collection.items, items = _collection$items === void 0 ? [] : _collection$items;
newCollection = _objectSpread({}, collection);
selectedId = selectedItem ? selectedItem.id : null;
isGridViewEnabled = isFeatureEnabled(features, 'contentExplorer.gridView.enabled');
itemThumbnails = [];
if (!isGridViewEnabled) {
_context.next = 12;
break;
}
fileAPI = this.api.getFileAPI(false);
_context.next = 11;
return Promise.all(items.map(function (item) {
return fileAPI.getThumbnailUrl(item);
}));
case 11:
itemThumbnails = _context.sent;
case 12:
newCollection.items = items.map(function (obj, index) {
var isSelected = obj.id === selectedId;
var currentItem = isSelected ? selectedItem : obj;
var thumbnailUrl = isGridViewEnabled ? itemThumbnails[index] : null;
var newItem = _objectSpread({}, currentItem, {
selected: isSelected,
thumbnailUrl: thumbnailUrl
}); // Only if selectedItem is in the current collection do we want to set selected state
if (isSelected) {
newSelectedItem = newItem;
}
return newItem;
});
this.setState({
currentCollection: newCollection,
selected: newSelectedItem
}, callback);
case 14:
case "end":
return _context.stop();
}
}
}, _callee, this);
}));
return function updateCollection(_x, _x2) {
return _updateCollection.apply(this, arguments);
};
}()
/**
* Selects or unselects an item
*
* @private
* @param {Object} item - file or folder object
* @param {Function|void} [onSelect] - optional on select callback
* @return {void}
*/
}, {
key: "render",
/**
* Renders the file picker
*
* @private
* @inheritdoc
* @return {Element}
*/
value: function render() {
var _this$props9 = this.props,
language = _this$props9.language,
messages = _this$props9.messages,
rootFolderId = _this$props9.rootFolderId,
logoUrl = _this$props9.logoUrl,
canUpload = _this$props9.canUpload,
canCreateNewFolder = _this$props9.canCreateNewFolder,
canSetShareAccess = _this$props9.canSetShareAccess,
canDelete = _this$props9.canDelete,
canRename = _this$props9.canRename,
canDownload = _this$props9.canDownload,
canPreview = _this$props9.canPreview,
canShare = _this$props9.canShare,
token = _this$props9.token,
sharedLink = _this$props9.sharedLink,
sharedLinkPassword = _this$props9.sharedLinkPassword,
apiHost = _this$props9.apiHost,
appHost = _this$props9.appHost,
staticHost = _this$props9.staticHost,
uploadHost = _this$props9.uploadHost,
isSmall = _this$props9.isSmall,
isMedium = _this$props9.isMedium,
isTouch = _this$props9.isTouch,
className = _this$props9.className,
measureRef = _this$props9.measureRef,
onPreview = _this$props9.onPreview,
onDownload = _this$props9.onDownload,
onUpload = _this$props9.onUpload,
requestInterceptor = _this$props9.requestInterceptor,
responseInterceptor = _this$props9.responseInterceptor,
contentPreviewProps = _this$props9.contentPreviewProps,
metadataColumnsToShow = _this$props9.metadataColumnsToShow;
var _this$state10 = this.state,
view = _this$state10.view,
rootName = _this$state10.rootName,
currentCollection = _this$state10.currentCollection,
currentPageSize = _this$state10.currentPageSize,
searchQuery = _this$state10.searchQuery,
gridColumnCount = _this$state10.gridColumnCount,
isDeleteModalOpen = _this$state10.isDeleteModalOpen,
isRenameModalOpen = _this$state10.isRenameModalOpen,
isShareModalOpen = _this$state10.isShareModalOpen,
isUploadModalOpen = _this$state10.isUploadModalOpen,
isPreviewModalOpen = _this$state10.isPreviewModalOpen,
isCreateFolderModalOpen = _this$state10.isCreateFolderModalOpen,
selected = _this$state10.selected,
isLoading = _this$state10.isLoading,
errorCode = _this$state10.errorCode,
focusedRow = _this$state10.focusedRow;
var id = currentCollection.id,
offset = currentCollection.offset,
permissions = currentCollection.permissions,
totalCount = currentCollection.totalCount;
var _ref3 = permissions || {},
can_upload = _ref3.can_upload;
var styleClassName = classNames('be bce', className);
var allowUpload = canUpload && !!can_upload;
var allowCreate = canCreateNewFolder && !!can_upload;
var viewMode = this.getViewMode();
var maxGridColumnCount = this.getMaxNumberOfGridViewColumnsForWidth();
/* eslint-disable jsx-a11y/no-static-element-interactions */
/* eslint-disable jsx-a11y/no-noninteractive-tabindex */
return React.createElement(Internationalize, {
language: language,
messages: messages
}, React.createElement("div", {
id: this.id,
className: styleClassName,
ref: measureRef
}, React.createElement("div", {
className: "be-app-element",
onKeyDown: this.onKeyDown,
tabIndex: 0
}, React.createElement(Header, {
view: view,
isSmall: isSmall,
searchQuery: searchQuery,
logoUrl: logoUrl,
onSearch: this.search,
canSearch: viewMode !== VIEW_MODE_METADATA_BASED_LIST
}), React.createElement(SubHeader, {
view: view,
viewMode: viewMode,
rootId: rootFolderId,
isSmall: isSmall,
rootName: rootName,
currentCollection: currentCollection,
canUpload: allowUpload,
canCreateNewFolder: allowCreate,
gridColumnCount: gridColumnCount,
gridMaxColumns: GRID_VIEW_MAX_COLUMNS,
gridMinColumns: GRID_VIEW_MIN_COLUMNS,
maxGridColumnCountForWidth: maxGridColumnCount,
onUpload: this.upload,
onCreate: this.createFolder,
onGridViewSliderChange: this.onGridViewSliderChange,
onItemClick: this.fetchFolder,
onSortChange: this.sort,
onViewModeChange: this.changeViewMode
}), React.createElement(Content, {
canDelete: canDelete,
canDownload: canDownload,
canPreview: canPreview,
canRename: canRename,
canSetShareAccess: canSetShareAccess,
canShare: canShare,
currentCollection: currentCollection,
focusedRow: focusedRow,
gridColumnCount: Math.min(gridColumnCount, maxGridColumnCount),
isMedium: isMedium,
isSmall: isSmall,
isTouch: isTouch,
onItemClick: this.onItemClick,
onItemDelete: this.delete,
onItemDownload: this.download,
onItemPreview: this.preview,
onItemRename: this.rename,
onItemSelect: this.select,
onItemShare: this.share,
onSortChange: this.sort,
rootElement: this.rootElement,
rootId: rootFolderId,
tableRef: this.tableRef,
view: view,
viewMode: viewMode,
metadataColumnsToShow: metadataColumnsToShow
}), React.createElement(Footer, null, React.createElement(Pagination, {
offset: offset,
onChange: this.paginate,
pageSize: currentPageSize,
totalCount: totalCount
}))), allowUpload && !!this.appElement ? React.createElement(UploadDialog, {
isOpen: isUploadModalOpen,
currentFolderId: id,
token: token,
sharedLink: sharedLink,
sharedLinkPassword: sharedLinkPassword,
apiHost: apiHost,
uploadHost: uploadHost,
onClose: this.uploadSuccessHandler,
parentElement: this.rootElement,
appElement: this.appElement,
onUpload: onUpload,
requestInterceptor: requestInterceptor,
responseInterceptor: responseInterceptor
}) : null, allowCreate && !!this.appElement ? React.createElement(CreateFolderDialog, {
isOpen: isCreateFolderModalOpen,
onCreate: this.createFolderCallback,
onCancel: this.closeModals,
isLoading: isLoading,
errorCode: errorCode,
parentElement: this.rootElement,
appElement: this.appElement
}) : null, canDelete && selected && !!this.appElement ? React.createElement(DeleteConfirmationDialog, {
isOpen: isDeleteModalOpen,
onDelete: this.deleteCallback,
onCancel: this.closeModals,
item: selected,
isLoading: isLoading,
parentElement: this.rootElement,
appElement: this.appElement
}) : null, canRename && selected && !!this.appElement ? React.createElement(RenameDialog, {
isOpen: isRenameModalOpen,
onRename: this.renameCallback,
onCancel: this.closeModals,
item: selected,
isLoading: isLoading,
errorCode: errorCode,
parentElement: this.rootElement,
appElement: this.appElement
}) : null, canShare && selected && !!this.appElement ? React.createElement(ShareDialog, {
isOpen: isShareModalOpen,
canSetShareAccess: canSetShareAccess,
onShareAccessChange: this.changeShareAccess,
onCancel: this.refreshCollection,
item: selected,
isLoading: isLoading,
parentElement: this.rootElement,
appElement: this.appElement
}) : null, canPreview && selected && !!this.appElement ? React.createElement(PreviewDialog, {
isOpen: isPreviewModalOpen,
isTouch: isTouch,
onCancel: this.closeModals,
item: selected,
currentCollection: currentCollection,
token: token,
parentElement: this.rootElement,
appElement: this.appElement,
onPreview: onPreview,
onDownload: onDownload,
canDownload: canDownload,
cache: this.api.getCache(),
ap