synapse-react-client
Version:
[](https://travis-ci.com/Sage-Bionetworks/Synapse-React-Client) [](https://badge.fury.io/js/synaps
291 lines • 15.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TreeView = exports.FinderScope = void 0;
var tslib_1 = require("tslib");
var react_1 = (0, tslib_1.__importStar)(require("react"));
var react_bootstrap_1 = require("react-bootstrap");
var react_error_boundary_1 = require("react-error-boundary");
var react_intersection_observer_1 = require("react-intersection-observer");
var utils_1 = require("../../../utils");
var EntityTypeUtils_1 = require("../../../utils/functions/EntityTypeUtils");
var RegularExpressions_1 = require("../../../utils/functions/RegularExpressions");
var useEntityBundle_1 = (0, tslib_1.__importDefault)(require("../../../utils/hooks/SynapseAPI/useEntityBundle"));
var useProjects_1 = require("../../../utils/hooks/SynapseAPI/useProjects");
var SynapseContext_1 = require("../../../utils/SynapseContext");
var synapseTypes_1 = require("../../../utils/synapseTypes");
var LoadingScreen_1 = require("../../LoadingScreen");
var EntityDetailsList_1 = require("../details/EntityDetailsList");
var TreeNode_1 = require("./TreeNode");
var isEntityIdInPath = function (entityId, path) {
for (var _i = 0, _a = path.path; _i < _a.length; _i++) {
var eh = _a[_i];
if (entityId === eh.id) {
return true;
}
}
return false;
};
var FinderScope;
(function (FinderScope) {
FinderScope["CURRENT_PROJECT"] = "Current Project";
FinderScope["ALL_PROJECTS"] = "All Projects";
FinderScope["CREATED_BY_ME"] = "Projects Created By Me";
FinderScope["FAVORITES"] = "My Favorites";
})(FinderScope = exports.FinderScope || (exports.FinderScope = {}));
function getScopeOptionNodeName(scope) {
switch (scope) {
case FinderScope.CURRENT_PROJECT:
case FinderScope.ALL_PROJECTS:
case FinderScope.CREATED_BY_ME:
return 'Projects';
case FinderScope.FAVORITES:
return 'Favorites';
}
}
/**
* The TreeView displays a user's entities hierarchically, allowing a user to quickly dive into an entity tree.
*
* The tree view currently can only be used to drive a DetailsView using the `setDetailsViewConfiguration` property.
*/
var TreeView = function (_a) {
var _b = _a.initialScope, initialScope = _b === void 0 ? FinderScope.CURRENT_PROJECT : _b, projectId = _a.projectId, _c = _a.initialContainer, initialContainer = _c === void 0 ? null : _c, _d = _a.visibleTypes, visibleTypes = _d === void 0 ? [synapseTypes_1.EntityType.PROJECT, synapseTypes_1.EntityType.FOLDER] : _d, toggleSelection = _a.toggleSelection, selectedEntities = _a.selectedEntities, setDetailsViewConfiguration = _a.setDetailsViewConfiguration, setBreadcrumbItems = _a.setBreadcrumbItems, _e = _a.showScopeAsRootNode, showScopeAsRootNode = _e === void 0 ? true : _e, nodeAppearance = _a.nodeAppearance, selectableTypes = _a.selectableTypes;
var DEFAULT_CONFIGURATION = {
type: EntityDetailsList_1.EntityDetailsListDataConfigurationType.PROMPT,
};
var accessToken = (0, SynapseContext_1.useSynapseContext)().accessToken;
var _f = (0, react_1.useState)(false), isLoading = _f[0], setIsLoading = _f[1];
var _g = (0, react_1.useState)([]), topLevelEntities = _g[0], setTopLevelEntities = _g[1];
var _h = (0, react_1.useState)(initialScope), scope = _h[0], setScope = _h[1];
var _j = (0, react_1.useState)(), initialContainerPath = _j[0], setInitialContainerPath = _j[1];
var _k = (0, react_1.useState)(nodeAppearance === TreeNode_1.NodeAppearance.BROWSE
? initialContainer
: initialContainer), currentContainer = _k[0], setCurrentContainer = _k[1];
var handleError = (0, react_error_boundary_1.useErrorHandler)();
(0, react_1.useEffect)(function () {
if (setDetailsViewConfiguration) {
setDetailsViewConfiguration(DEFAULT_CONFIGURATION);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
var setSelectedId = (0, react_1.useCallback)(function (entityId) {
if (toggleSelection) {
toggleSelection({ targetId: entityId });
}
setCurrentContainer(entityId);
}, [toggleSelection]);
// For these scopes, use the `useGetProjectsInfinite` hook
var useProjectData = scope === FinderScope.ALL_PROJECTS || scope === FinderScope.CREATED_BY_ME;
var _l = (0, useProjects_1.useGetProjectsInfinite)(scope === FinderScope.CREATED_BY_ME
? { filter: 'CREATED', sort: 'PROJECT_NAME', sortDirection: 'ASC' }
: { sort: 'PROJECT_NAME', sortDirection: 'ASC' }, {
enabled: useProjectData,
}), projectData = _l.data, isSuccessProjects = _l.isSuccess, fetchNextPageProjects = _l.fetchNextPage, hasNextPageProjects = _l.hasNextPage, isLoadingProjects = _l.isLoading;
var _m = (0, useEntityBundle_1.default)(currentContainer, undefined, undefined, {
enabled: !!currentContainer && currentContainer !== 'root',
}), currentContainerBundle = _m.data, isSuccessBundle = _m.isSuccess;
var _o = (0, react_intersection_observer_1.useInView)({ rootMargin: '500px' }), ref = _o.ref, inView = _o.inView;
(0, react_1.useEffect)(function () {
if (useProjectData && isSuccessProjects) {
if (projectData === null || projectData === void 0 ? void 0 : projectData.pages) {
setTopLevelEntities(projectData.pages.flatMap(function (page) { return page.results; }));
}
}
}, [useProjectData, isSuccessProjects, projectData]);
(0, react_1.useEffect)(function () {
if (useProjectData && inView && hasNextPageProjects && !isLoadingProjects) {
fetchNextPageProjects();
}
}, [
useProjectData,
inView,
hasNextPageProjects,
fetchNextPageProjects,
scope,
isLoadingProjects,
]);
// Populates the first level of entities in the tree view
(0, react_1.useEffect)(function () {
setIsLoading(true);
switch (scope) {
case FinderScope.ALL_PROJECTS:
case FinderScope.CREATED_BY_ME:
setIsLoading(isLoadingProjects);
// See the useGetProjectsInfinite hook
break;
case FinderScope.FAVORITES: {
utils_1.SynapseClient.getUserFavorites(accessToken).then(function (_a) {
var results = _a.results;
// TODO: https://sagebionetworks.jira.com/browse/PLFM-6652
results = results.filter(function (result) {
return visibleTypes.includes((0, EntityTypeUtils_1.convertToEntityType)(result.type));
});
setTopLevelEntities(results);
setIsLoading(false);
});
break;
}
case FinderScope.CURRENT_PROJECT:
if (projectId) {
if (initialContainer === null || initialContainer === void 0 ? void 0 : initialContainer.match(RegularExpressions_1.SYNAPSE_ENTITY_ID_REGEX)) {
utils_1.SynapseClient.getEntityPath(initialContainer, accessToken)
.then(function (path) {
if (!path.path.map(function (entity) { return entity.id; }).includes(projectId)) {
handleError(new Error("An initial container (" + initialContainer + ") was provided but is not within or the same as the provided project (" + projectId + ")"));
}
setInitialContainerPath(path);
setTopLevelEntities([path.path[1]]);
setIsLoading(false);
})
.catch(function (e) { return handleError(e); });
}
else {
utils_1.SynapseClient.getEntityHeader(projectId, accessToken)
.then(function (header) {
setTopLevelEntities([header]);
setIsLoading(false);
})
.catch(function (e) { return handleError(e); });
}
}
else {
handleError(new Error('Cannot open current project because the current project is unknown'));
}
break;
default:
handleError(new Error('No scope selected'));
}
}, [
accessToken,
scope,
initialContainer,
handleError,
visibleTypes,
isLoadingProjects,
projectId,
]);
// Creates the configuration for the details view and invokes the callback
(0, react_1.useEffect)(function () {
if (setDetailsViewConfiguration || setBreadcrumbItems) {
var detailsViewConfig = void 0;
var breadcrumbItems = [];
if (currentContainer === null) {
detailsViewConfig = {
type: EntityDetailsList_1.EntityDetailsListDataConfigurationType.PROMPT,
};
breadcrumbItems = [];
}
else if (currentContainer === 'root') {
switch (scope) {
case FinderScope.ALL_PROJECTS:
detailsViewConfig = {
type: EntityDetailsList_1.EntityDetailsListDataConfigurationType.USER_PROJECTS,
};
break;
case FinderScope.CREATED_BY_ME:
detailsViewConfig = {
type: EntityDetailsList_1.EntityDetailsListDataConfigurationType.USER_PROJECTS,
getProjectParams: {
filter: 'CREATED',
},
};
break;
case FinderScope.CURRENT_PROJECT:
detailsViewConfig = {
type: EntityDetailsList_1.EntityDetailsListDataConfigurationType.HEADER_LIST,
headerList: topLevelEntities,
};
break;
case FinderScope.FAVORITES:
detailsViewConfig = {
type: EntityDetailsList_1.EntityDetailsListDataConfigurationType.USER_FAVORITES,
};
break;
}
breadcrumbItems = [
{
name: scope,
isCurrent: true,
action: function () {
setCurrentContainer('root');
},
},
];
}
else {
detailsViewConfig = {
type: EntityDetailsList_1.EntityDetailsListDataConfigurationType.PARENT_CONTAINER,
parentContainerId: currentContainer,
};
if (isSuccessBundle) {
breadcrumbItems = (0, tslib_1.__spreadArray)([
{
name: scope,
isCurrent: false,
action: function () {
setCurrentContainer('root');
},
}
], currentContainerBundle
.path.path.slice(1) // Remove the root entity, syn4489
.map(function (entity) {
return {
name: entity.name,
isCurrent: entity.id === currentContainer,
action: function () {
setCurrentContainer(entity.id);
},
};
}), true);
}
}
if (setDetailsViewConfiguration) {
setDetailsViewConfiguration(detailsViewConfig);
}
if (setBreadcrumbItems) {
setBreadcrumbItems(breadcrumbItems);
}
}
}, [
scope,
currentContainer,
topLevelEntities,
setDetailsViewConfiguration,
setBreadcrumbItems,
currentContainerBundle,
isSuccessBundle,
]);
var rootNodeConfiguration = {
nodeText: getScopeOptionNodeName(scope),
children: topLevelEntities,
};
var shouldAutoExpand = (0, react_1.useCallback)(function (entityId) {
return !!(scope === FinderScope.CURRENT_PROJECT &&
initialContainerPath &&
isEntityIdInPath(entityId, initialContainerPath));
}, [scope, initialContainerPath]);
return (react_1.default.createElement("div", { className: "TreeView " + (nodeAppearance === TreeNode_1.NodeAppearance.SELECT ? 'SelectTree' : 'BrowseTree') },
react_1.default.createElement("div", { className: "Header" },
react_1.default.createElement("div", { className: "Browse" }, "Browse:"),
react_1.default.createElement("div", { onClick: function (e) { return e.stopPropagation(); } },
react_1.default.createElement(react_bootstrap_1.Dropdown, null,
react_1.default.createElement(react_bootstrap_1.Dropdown.Toggle, { variant: "gray-primary-500", id: "dropdown-basic" }, scope),
react_1.default.createElement(react_bootstrap_1.Dropdown.Menu, { role: "menu" }, Object.values(FinderScope).map(function (scopeOption) {
if (scopeOption === FinderScope.CURRENT_PROJECT &&
projectId == null) {
return react_1.default.createElement(react_1.default.Fragment, { key: scopeOption });
}
return (react_1.default.createElement(react_bootstrap_1.Dropdown.Item, { role: "menuitem", key: scopeOption, onClick: function (e) {
e.stopPropagation();
if (scope !== scopeOption) {
setScope(scopeOption);
setCurrentContainer(null);
}
} }, scopeOption));
}))))),
isLoading ? (react_1.default.createElement("div", { className: "Placeholder" },
react_1.default.createElement(LoadingScreen_1.SynapseSpinner, { size: 30 }))) : (react_1.default.createElement("div", { className: "Tree", role: "tree" },
showScopeAsRootNode ? (react_1.default.createElement(TreeNode_1.TreeNode, { level: 0, selected: selectedEntities, setSelectedId: setSelectedId, visibleTypes: visibleTypes, autoExpand: shouldAutoExpand, rootNodeConfiguration: rootNodeConfiguration, appearance: nodeAppearance, selectableTypes: selectableTypes })) : (topLevelEntities.map(function (entity) { return (react_1.default.createElement(TreeNode_1.TreeNode, { key: entity.id, level: 0, selected: selectedEntities, setSelectedId: setSelectedId, visibleTypes: visibleTypes, autoExpand: shouldAutoExpand, entityHeader: entity, appearance: nodeAppearance, selectableTypes: selectableTypes })); })),
react_1.default.createElement("div", { ref: ref, style: { height: '5px', width: '100%' } })))));
};
exports.TreeView = TreeView;
//# sourceMappingURL=TreeView.js.map