synapse-react-client
Version:
[](https://travis-ci.com/Sage-Bionetworks/Synapse-React-Client) [](https://badge.fury.io/js/synaps
428 lines • 26.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TESTING_CLEAR_BTN_CLASS = exports.TESTING_TRASH_BTN_CLASS = void 0;
var tslib_1 = require("tslib");
var fontawesome_svg_core_1 = require("@fortawesome/fontawesome-svg-core");
var free_solid_svg_icons_1 = require("@fortawesome/free-solid-svg-icons");
var react_fontawesome_1 = require("@fortawesome/react-fontawesome");
var moment_1 = (0, tslib_1.__importDefault)(require("moment"));
var react_1 = (0, tslib_1.__importStar)(require("react"));
var ReactBootstrap = (0, tslib_1.__importStar)(require("react-bootstrap"));
var calculateFriendlyFileSize_1 = require("../../utils/functions/calculateFriendlyFileSize");
var useGetInfoFromIds_1 = (0, tslib_1.__importDefault)(require("../../utils/hooks/useGetInfoFromIds"));
var SynapseClient_1 = require("../../utils/SynapseClient");
var synapseTypes_1 = require("../../utils/synapseTypes");
var HasAccess_1 = (0, tslib_1.__importStar)(require("../HasAccess"));
var UserCard_1 = (0, tslib_1.__importDefault)(require("../UserCard"));
var CreatePackage_1 = require("./CreatePackage");
var DownloadDetails_1 = (0, tslib_1.__importDefault)(require("./DownloadDetails"));
var AccessRequirementList_1 = (0, tslib_1.__importDefault)(require("../access_requirement_list/AccessRequirementList"));
var SynapseContext_1 = require("../../utils/SynapseContext");
var getEndpoint_1 = require("../../utils/functions/getEndpoint");
fontawesome_svg_core_1.library.add(free_solid_svg_icons_1.faTrash);
exports.TESTING_TRASH_BTN_CLASS = 'TESTING_TRASH_BTN_CLASS';
exports.TESTING_CLEAR_BTN_CLASS = 'TESTING_CLEAR_BTN_CLASS';
/**
* Web-based download list.
*
* @deprecated Use the new Download List Services instead (that support the Download Cart).
* http://rest-docs.synapse.org/rest/#org.sagebionetworks.repo.web.controller.DownloadListController
*/
function DownloadListTable(props) {
var _this = this;
var _a, _b;
var accessToken = (0, SynapseContext_1.useSynapseContext)().accessToken;
// https://reactjs.org/docs/hooks-faq.html#should-i-use-one-or-many-state-variables
var _c = (0, react_1.useState)({
references: undefined,
batchFileResult: undefined,
downloadList: undefined,
}), data = _c[0], setData = _c[1];
var _d = (0, react_1.useState)({
column: '',
isDescending: false,
}), sortedColumn = _d[0], setSortedColumn = _d[1];
var _e = (0, react_1.useState)(), arPropsFromHasAccess = _e[0], set_arPropsFromHasAccess = _e[1];
// https://reactjs.org/docs/hooks-faq.html#should-i-use-one-or-many-state-variables
var _f = (0, react_1.useState)(true), isLoading = _f[0], setIsLoading = _f[1];
var _g = (0, react_1.useState)(''), fileBeingDeleted = _g[0], setFileBeingDeleted = _g[1];
var _h = props.forceSamePage, forceSamePage = _h === void 0 ? false : _h, _j = props.renderAsModal, renderAsModal = _j === void 0 ? false : _j, onHide = props.onHide, listUpdatedCallback = props.listUpdatedCallback;
var references = data.references, batchFileResult = data.batchFileResult, downloadList = data.downloadList;
var requestedFiles = (batchFileResult && batchFileResult.requestedFiles) || [];
// Get owner ids from download list by filtering to items that have a file handle
// then map to ownerIds
var ownerIdsFromHeaders = references === null || references === void 0 ? void 0 : references.results.filter(function (el) { return el.createdBy; }).map(function (el) { return el.createdBy; });
var ownerIdsFromFileHandles = requestedFiles
.filter(function (el) { var _a; return ((_a = el.fileHandle) === null || _a === void 0 ? void 0 : _a.createdBy) !== undefined; })
.map(function (el) { return el.fileHandle.createdBy; });
var ownerIds = [];
if (ownerIdsFromFileHandles) {
ownerIds.push.apply(ownerIds, ownerIdsFromFileHandles);
}
if (ownerIdsFromHeaders) {
ownerIds.push.apply(ownerIds, ownerIdsFromHeaders);
}
// use bang operator because filter function guarentee's that file handle will be defined
var userProfiles = (0, useGetInfoFromIds_1.default)({
ids: ownerIds,
type: 'USER_PROFILE',
});
var fetchData = (0, react_1.useCallback)(function () { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
var currentDownloadList, currentFilesToDownload, batchFileRequest, currentBatchFileResult_1, referenceCall, currentReferences, e_1;
return (0, tslib_1.__generator)(this, function (_a) {
switch (_a.label) {
case 0:
if (!accessToken) {
setIsLoading(false);
// doesn't make sense with anonymous user!
return [2 /*return*/];
}
_a.label = 1;
case 1:
_a.trys.push([1, 5, 6, 7]);
setIsLoading(true);
return [4 /*yield*/, (0, SynapseClient_1.getDownloadList)(accessToken)];
case 2:
currentDownloadList = _a.sent();
currentFilesToDownload = currentDownloadList.filesToDownload;
if (currentFilesToDownload.length === 0) {
setData({
downloadList: currentDownloadList,
});
return [2 /*return*/];
}
batchFileRequest = {
requestedFiles: currentFilesToDownload,
includeFileHandles: true,
includePreSignedURLs: false,
includePreviewPreSignedURLs: false,
};
return [4 /*yield*/, (0, SynapseClient_1.getFiles)(batchFileRequest, accessToken)
// Only make entity header calls to the files that the user doesn't have access to,
// which can be determined by whether the batchFileResult has a failure code for the
// corresponding download list item
];
case 3:
currentBatchFileResult_1 = _a.sent();
referenceCall = currentFilesToDownload
.filter(function (el) {
return (currentBatchFileResult_1.requestedFiles.find(function (batchFile) { return batchFile.fileHandleId === el.fileHandleId; }).failureCode !== undefined);
})
.map(function (el) {
return { targetId: el.associateObjectId };
});
return [4 /*yield*/, (0, SynapseClient_1.getEntityHeaders)(referenceCall, accessToken)];
case 4:
currentReferences = _a.sent();
setData({
references: currentReferences,
batchFileResult: currentBatchFileResult_1,
downloadList: currentDownloadList,
});
return [3 /*break*/, 7];
case 5:
e_1 = _a.sent();
console.error('Error in DownloadList API call : ', e_1);
return [3 /*break*/, 7];
case 6:
setIsLoading(false);
return [7 /*endfinally*/];
case 7: return [2 /*return*/];
}
});
}); }, [accessToken]);
(0, react_1.useEffect)(function () {
fetchData();
}, [fetchData]);
var clearDownloadList = function (_event) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
var err_1;
return (0, tslib_1.__generator)(this, function (_a) {
switch (_a.label) {
case 0:
setIsLoading(true);
_a.label = 1;
case 1:
_a.trys.push([1, 3, 4, 5]);
return [4 /*yield*/, (0, SynapseClient_1.deleteDownloadList)(accessToken)];
case 2:
_a.sent();
setData({
downloadList: undefined,
});
listUpdatedCallback === null || listUpdatedCallback === void 0 ? void 0 : listUpdatedCallback();
return [3 /*break*/, 5];
case 3:
err_1 = _a.sent();
console.error('Error on clearing download list: ', err_1);
return [3 /*break*/, 5];
case 4:
setIsLoading(false);
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
var deleteFileFromList = function (fileHandleId, associateObjectId) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
var list, currentDownloadList, err_2;
return (0, tslib_1.__generator)(this, function (_a) {
switch (_a.label) {
case 0:
list = [
{
fileHandleId: fileHandleId,
associateObjectId: associateObjectId,
associateObjectType: synapseTypes_1.FileHandleAssociateType.FileEntity,
},
];
setIsLoading(true);
setFileBeingDeleted(fileHandleId);
_a.label = 1;
case 1:
_a.trys.push([1, 3, 4, 5]);
return [4 /*yield*/, (0, SynapseClient_1.deleteDownloadListFiles)(list, accessToken)
// The current references and batchFileResult can be kept because the download
// list drives the view, so the stale values in those two won't be viewed.
];
case 2:
currentDownloadList = _a.sent();
// The current references and batchFileResult can be kept because the download
// list drives the view, so the stale values in those two won't be viewed.
setData({
downloadList: currentDownloadList,
references: references,
batchFileResult: batchFileResult,
});
listUpdatedCallback === null || listUpdatedCallback === void 0 ? void 0 : listUpdatedCallback();
return [3 /*break*/, 5];
case 3:
err_2 = _a.sent();
console.error('Error on delete from download list', err_2);
return [3 /*break*/, 5];
case 4:
setFileBeingDeleted('');
setIsLoading(false);
return [7 /*endfinally*/];
case 5: return [2 /*return*/];
}
});
}); };
var sortColumn = function (column) { return (0, tslib_1.__awaiter)(_this, void 0, void 0, function () {
var isDescending_1, currentFilesToDownload;
var _a;
return (0, tslib_1.__generator)(this, function (_b) {
try {
setIsLoading(true);
isDescending_1 = column === sortedColumn.column ? !sortedColumn.isDescending : false;
setSortedColumn({
column: column,
isDescending: isDescending_1,
});
currentFilesToDownload = (_a = downloadList === null || downloadList === void 0 ? void 0 : downloadList.filesToDownload) !== null && _a !== void 0 ? _a : [];
currentFilesToDownload.sort(function (itemA, itemB) {
return sortDownLoadList(itemA, itemB, column, isDescending_1);
});
setData((0, tslib_1.__assign)((0, tslib_1.__assign)({}, data), { downloadList: downloadList }));
listUpdatedCallback === null || listUpdatedCallback === void 0 ? void 0 : listUpdatedCallback();
}
catch (err) {
console.error(err);
}
finally {
setIsLoading(false);
}
return [2 /*return*/];
});
}); };
var getFileHandleInfo = function (item) {
var _a;
var fileResult = requestedFiles.find(function (fileRes) { return fileRes.fileHandleId === item.fileHandleId; });
var fileHandle = fileResult ? fileResult.fileHandle : undefined;
var fileName = '';
var createdBy = '';
var createdOn = '';
var contentSize = undefined;
if (fileHandle && item) {
fileName = fileHandle.fileName;
createdBy = fileHandle.createdBy;
createdOn = fileHandle.createdOn;
contentSize = fileHandle.contentSize;
}
else {
var requestedFile = results.find(function (req) { return req.id === item.associateObjectId; });
if (requestedFiles) {
fileName = requestedFile === null || requestedFile === void 0 ? void 0 : requestedFile.name;
createdBy = requestedFile === null || requestedFile === void 0 ? void 0 : requestedFile.createdBy;
createdOn = requestedFile === null || requestedFile === void 0 ? void 0 : requestedFile.createdOn;
}
}
createdBy = (_a = userProfiles.find(function (el) { return el.ownerId === createdBy; })) === null || _a === void 0 ? void 0 : _a.userName;
return { fileName: fileName, createdBy: createdBy, createdOn: createdOn, contentSize: contentSize };
};
var sortDownLoadList = function (itemA, itemB, column, isDescending) {
var _a = getFileHandleInfo(itemA), fileName_A = _a.fileName, createdBy_A = _a.createdBy, createdOn_A = _a.createdOn, contentSize_A = _a.contentSize;
var _b = getFileHandleInfo(itemB), fileName_B = _b.fileName, createdBy_B = _b.createdBy, createdOn_B = _b.createdOn, contentSize_B = _b.contentSize;
var direction = isDescending ? 1 : -1;
switch (column) {
case 'file':
return (fileName_B === null || fileName_B === void 0 ? void 0 : fileName_B.localeCompare(fileName_A)) * direction;
case 'createdBy':
return (createdBy_B === null || createdBy_B === void 0 ? void 0 : createdBy_B.localeCompare(createdBy_A)) * direction;
case 'createdOn':
return (createdOn_B === null || createdOn_B === void 0 ? void 0 : createdOn_B.localeCompare(createdOn_A)) * direction;
case 'size':
if (contentSize_A && !contentSize_B) {
return -1;
}
else if (contentSize_B && !contentSize_A) {
return 1;
}
else {
return (contentSize_B - contentSize_A) * direction;
}
default:
return 1;
}
};
var filesToDownload = (_a = downloadList === null || downloadList === void 0 ? void 0 : downloadList.filesToDownload) !== null && _a !== void 0 ? _a : [];
var results = (_b = references === null || references === void 0 ? void 0 : references.results) !== null && _b !== void 0 ? _b : [];
var numBytes = 0;
var numFiles = 0;
var content = (react_1.default.createElement("div", { className: "DownloadListTable" },
react_1.default.createElement("div", { style: { display: arPropsFromHasAccess ? 'none' : '' } },
react_1.default.createElement("div", { className: "SRC-split download-list-table-top SRC-primary-background-color SRC-border-bottom-only" },
react_1.default.createElement("span", { className: "create-package-text" },
"Download List \u00A0\u00A0",
isLoading && react_1.default.createElement("span", { className: "spinner" })),
react_1.default.createElement("button", { className: "SRC-underline-on-hover uppercase-text", onClick: clearDownloadList, id: exports.TESTING_CLEAR_BTN_CLASS }, "Clear list")),
react_1.default.createElement(ReactBootstrap.Table, { striped: true, responsive: true },
react_1.default.createElement("thead", null,
react_1.default.createElement("tr", null,
react_1.default.createElement("th", null,
"File",
react_1.default.createElement("button", { className: "sort SRC-primary-background-color-hover " + (sortedColumn.column === 'file'
? 'SRC-primary-background-color'
: ''), onClick: function () {
sortColumn('file');
} },
react_1.default.createElement(react_fontawesome_1.FontAwesomeIcon, { icon: sortedColumn.column === 'file'
? sortedColumn.isDescending === false
? free_solid_svg_icons_1.faSortAmountDown
: free_solid_svg_icons_1.faSortAmountUp
: free_solid_svg_icons_1.faSortAmountDown, color: sortedColumn.column === 'file' ? 'white' : '' }))),
react_1.default.createElement("th", null, "Access"),
react_1.default.createElement("th", null,
"Created By",
react_1.default.createElement("button", { className: "sort SRC-primary-background-color-hover " + (sortedColumn.column === 'createdBy'
? 'SRC-primary-background-color'
: ''), onClick: function () {
sortColumn('createdBy');
} },
react_1.default.createElement(react_fontawesome_1.FontAwesomeIcon, { icon: sortedColumn.column === 'createdBy'
? sortedColumn.isDescending === false
? free_solid_svg_icons_1.faSortAmountDown
: free_solid_svg_icons_1.faSortAmountUp
: free_solid_svg_icons_1.faSortAmountDown, color: sortedColumn.column === 'createdBy' ? 'white' : '' }))),
react_1.default.createElement("th", null,
"Created On",
react_1.default.createElement("button", { className: "sort SRC-primary-background-color-hover " + (sortedColumn.column === 'createdOn'
? 'SRC-primary-background-color'
: ''), onClick: function () {
sortColumn('createdOn');
} },
react_1.default.createElement(react_fontawesome_1.FontAwesomeIcon, { icon: sortedColumn.column === 'createdOn'
? sortedColumn.isDescending === false
? free_solid_svg_icons_1.faSortAmountDown
: free_solid_svg_icons_1.faSortAmountUp
: free_solid_svg_icons_1.faSortAmountDown, color: sortedColumn.column === 'createdOn' ? 'white' : '' }))),
react_1.default.createElement("th", null,
"Size",
react_1.default.createElement("button", { className: "sort SRC-primary-background-color-hover " + (sortedColumn.column === 'size'
? 'SRC-primary-background-color'
: ''), onClick: function () {
sortColumn('size');
} },
react_1.default.createElement(react_fontawesome_1.FontAwesomeIcon, { icon: sortedColumn.column === 'size'
? sortedColumn.isDescending === false
? free_solid_svg_icons_1.faSortAmountDown
: free_solid_svg_icons_1.faSortAmountUp
: free_solid_svg_icons_1.faSortAmountDown, color: sortedColumn.column === 'size' ? 'white' : '' }))),
react_1.default.createElement("th", null))),
react_1.default.createElement("tbody", { className: "download-list-table" }, filesToDownload.map(function (item) {
var createdBy = '';
var createdOn = '';
var fileName = '';
var contentSize = undefined;
var synId = item.associateObjectId;
var fileHandleId = item.fileHandleId;
var isCurrentlyBeingDeletedClass = fileBeingDeleted === fileHandleId ? 'SRC-inactive-bg' : '';
// See if batch file results has this fileHandleId
var fileResult = requestedFiles.find(function (fileRes) { return fileRes.fileHandleId === fileHandleId; });
var fileHandle = fileResult === null || fileResult === void 0 ? void 0 : fileResult.fileHandle;
var canDownload = fileHandle !== undefined;
if (fileHandle) {
// fileHandle is defined, this file is downloadable, show its metadata
;
(createdBy = fileHandle.createdBy, createdOn = fileHandle.createdOn, fileName = fileHandle.fileName, contentSize = fileHandle.contentSize);
if ((0, HasAccess_1.getDownloadTypeForFileHandle)(fileHandle) ===
HasAccess_1.FileHandleDownloadTypeEnum.Accessible) {
numBytes += contentSize;
numFiles += 1;
}
}
else {
// file is not downloadable, only show its name from entity header info
var requestedFile = results.find(function (req) { return req.id === item.associateObjectId; });
fileName = requestedFile === null || requestedFile === void 0 ? void 0 : requestedFile.name;
createdBy = requestedFile === null || requestedFile === void 0 ? void 0 : requestedFile.createdBy;
createdOn = requestedFile === null || requestedFile === void 0 ? void 0 : requestedFile.createdOn;
}
createdOn = (0, moment_1.default)(createdOn).format('L LT');
var userProfile = userProfiles.find(function (el) { return el.ownerId === createdBy; });
return (react_1.default.createElement("tr", { className: isCurrentlyBeingDeletedClass, key: fileHandleId },
react_1.default.createElement("td", null,
react_1.default.createElement("a", { target: "_blank", rel: "noopener noreferrer", href: getEndpoint_1.PRODUCTION_ENDPOINT_CONFIG.PORTAL + "#!Synapse:" + synId }, fileName)),
react_1.default.createElement("td", null,
react_1.default.createElement(HasAccess_1.default, { onHide: onHide, fileHandle: fileHandle, set_arPropsFromHasAccess: set_arPropsFromHasAccess, entityId: synId, isInDownloadList: true, forceSamePage: forceSamePage })),
react_1.default.createElement("td", null,
userProfile && (react_1.default.createElement(UserCard_1.default, { size: 'SMALL USER CARD', userProfile: userProfile, preSignedURL: userProfile.clientPreSignedURL })),
canDownload && !userProfile && (react_1.default.createElement("span", { className: "spinner" }))),
react_1.default.createElement("td", null, createdOn),
react_1.default.createElement("td", null, contentSize && (0, calculateFriendlyFileSize_1.calculateFriendlyFileSize)(contentSize)),
react_1.default.createElement("td", null,
react_1.default.createElement("button", { className: exports.TESTING_TRASH_BTN_CLASS, onClick: fileBeingDeleted === ''
? function () { return deleteFileFromList(fileHandleId, synId); }
: undefined },
react_1.default.createElement(react_fontawesome_1.FontAwesomeIcon, { className: "SRC-primary-text-color", icon: "trash" })))));
}))),
react_1.default.createElement(CreatePackage_1.CreatePackage, { updateDownloadList: fetchData },
react_1.default.createElement(DownloadDetails_1.default, { numBytes: numBytes, numFiles: numFiles }))),
arPropsFromHasAccess && (react_1.default.createElement(AccessRequirementList_1.default, (0, tslib_1.__assign)({}, arPropsFromHasAccess, { onHide: function () {
set_arPropsFromHasAccess(undefined);
} })))));
var onHideModal = (0, react_1.useCallback)(function () {
if (arPropsFromHasAccess) {
set_arPropsFromHasAccess(undefined);
}
else {
onHide === null || onHide === void 0 ? void 0 : onHide();
}
}, [arPropsFromHasAccess, onHide]);
if (renderAsModal) {
var closeBtn = {
position: 'absolute',
top: 5,
right: 20,
zIndex: 10,
};
return (react_1.default.createElement(ReactBootstrap.Modal, { centered: true, animation: false, size: 'lg', dialogClassName: 'download-list-modal-container', show: true },
react_1.default.createElement(ReactBootstrap.Modal.Header, null,
react_1.default.createElement("button", { style: closeBtn, onClick: onHideModal },
react_1.default.createElement(react_fontawesome_1.FontAwesomeIcon, { style: { fontSize: '21px' }, icon: "times" }))),
content));
}
else {
return content;
}
}
exports.default = DownloadListTable;
//# sourceMappingURL=DownloadListTable.js.map