synapse-react-client
Version:
[](https://travis-ci.com/Sage-Bionetworks/Synapse-React-Client) [](https://badge.fury.io/js/synaps
268 lines • 15.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.DatasetItemsEditor = void 0;
var tslib_1 = require("tslib");
var lab_1 = require("@material-ui/lab");
var react_base_table_1 = (0, tslib_1.__importDefault)(require("@sage-bionetworks/react-base-table"));
var react_1 = (0, tslib_1.__importStar)(require("react"));
var react_bootstrap_1 = require("react-bootstrap");
var react_tooltip_1 = (0, tslib_1.__importDefault)(require("react-tooltip"));
var SkeletonTable_1 = require("../../../assets/skeletons/SkeletonTable");
var TooltipUtils_1 = require("../../../utils/functions/TooltipUtils");
var useEntity_1 = require("../../../utils/hooks/SynapseAPI/useEntity");
var useSet_1 = require("../../../utils/hooks/useSet");
var useTraceUpdate_1 = (0, tslib_1.__importDefault)(require("../../../utils/hooks/useTraceUpdate"));
var synapseTypes_1 = require("../../../utils/synapseTypes");
var Typography_1 = (0, tslib_1.__importDefault)(require("../../../utils/typography/Typography"));
var EntityBadgeIcons_1 = require("../../EntityBadgeIcons");
var DetailsViewTableRenderers_1 = require("../../entity_finder/details/view/DetailsViewTableRenderers");
var EntityFinderModal_1 = require("../../entity_finder/EntityFinderModal");
var TreeView_1 = require("../../entity_finder/tree/TreeView");
var IconSvg_1 = (0, tslib_1.__importDefault)(require("../../IconSvg"));
var WarningModal_1 = (0, tslib_1.__importDefault)(require("../../synapse_form_wrapper/WarningModal"));
var ToastMessage_1 = require("../../ToastMessage");
var Checkbox_1 = require("../../widgets/Checkbox");
var ROW_HEIGHT = 42;
var TABLE_HEIGHT = 350;
function DatasetItemsEditor(props) {
var entityId = props.entityId, onSave = props.onSave, onClose = props.onClose;
var _a = (0, react_1.useState)(false), showEntityFinder = _a[0], setShowEntityFinder = _a[1];
var _b = (0, react_1.useState)(false), showWarningModal = _b[0], setShowWarningModal = _b[1];
// Disable updating the entity after the initial fetch because we don't want to replace edits that the user makes.
var _c = (0, react_1.useState)(), datasetToUpdate = _c[0], _setDatasetToUpdate = _c[1];
var setDatasetToUpdate = function (dataset) {
setHasChangedSinceLastSave(true);
_setDatasetToUpdate(dataset);
};
var _d = (0, react_1.useState)(false), hasChangedSinceLastSave = _d[0], setHasChangedSinceLastSave = _d[1];
var _e = (0, useSet_1.useSet)(), selectedIds = _e.set, addSelectedId = _e.add, removeSelectedId = _e.remove, clearSelectedIds = _e.clear;
var allItemsAreSelected = !!(datasetToUpdate && datasetToUpdate.items.length === selectedIds.size);
var refetch = (0, useEntity_1.useGetEntity)(entityId, undefined, {
enabled: !datasetToUpdate,
onSuccess: function (dataset) {
// SWC-5876: Dataset Items may be undefined. This has the same inherent meaning as the empty list, so we'll just change it to save us some null checks.
if (dataset.items == null) {
dataset.items = [];
}
setDatasetToUpdate(dataset);
setHasChangedSinceLastSave(false);
},
}).refetch;
var mutation = (0, useEntity_1.useUpdateEntity)({
onSuccess: function () {
(0, ToastMessage_1.displayToast)('Create a Version of this Dataset to freeze it in its current state', 'success', { title: 'Dataset Saved' });
if (onSave) {
onSave();
}
},
onError: function (error) {
if (error.status === 412) {
(0, ToastMessage_1.displayToast)('Re-retrieve the dataset to get the latest changes. Your current changes will be lost.', 'warning', {
title: 'Dataset Updated since Last Fetched',
primaryButtonText: 'Retrieve Dataset',
onPrimaryButtonClick: refetch,
});
}
else {
(0, ToastMessage_1.displayToast)(error.reason, 'danger', {
title: 'An Error Occurred',
});
}
},
});
var tableData = datasetToUpdate === null || datasetToUpdate === void 0 ? void 0 : datasetToUpdate.items.map(function (item) {
return (0, tslib_1.__assign)((0, tslib_1.__assign)({}, item), { isSelected: selectedIds.has(item.entityId), setSelected: function (value) {
return value
? addSelectedId(item.entityId)
: removeSelectedId(item.entityId);
} });
});
function addItemsToDataset(newItems) {
setDatasetToUpdate(function (datasetToUpdate) {
if (datasetToUpdate) {
var existingItems = datasetToUpdate.items.filter(function (item) { return !newItems.find(function (newItem) { return newItem.targetId === item.entityId; }); });
if (existingItems.length < datasetToUpdate.items.length) {
(0, ToastMessage_1.displayToast)('Files were added that were already in the dataset. The versions of those files might have been updated.', 'info');
}
var items = (0, tslib_1.__spreadArray)((0, tslib_1.__spreadArray)([], existingItems, true), newItems.map(function (item) { return ({
entityId: item.targetId,
versionNumber: item.targetVersionNumber,
}); }), true);
return (0, tslib_1.__assign)((0, tslib_1.__assign)({}, datasetToUpdate), { items: items });
}
else {
console.warn('Cannot add items to the Dataset because it is undefined. The Dataset may not have been fetched yet.');
return datasetToUpdate;
}
});
clearSelectedIds();
}
function removeSelectedItemsFromDataset() {
setDatasetToUpdate(function (dataset) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, dataset), { items: dataset.items.filter(function (datasetItem) { return !selectedIds.has(datasetItem.entityId); }) })); });
clearSelectedIds();
}
function changeVersionOnItem(entityId, newVersion) {
setDatasetToUpdate(function (dataset) { return ((0, tslib_1.__assign)((0, tslib_1.__assign)({}, dataset), { items: dataset.items.map(function (datasetItem) {
return datasetItem.entityId === entityId
? { entityId: entityId, versionNumber: newVersion }
: datasetItem;
}) })); });
}
var DatasetItemVersionRenderer = function (props) {
return (react_1.default.createElement(DetailsViewTableRenderers_1.DatasetEditorVersionRenderer, (0, tslib_1.__assign)({}, props, { toggleSelection: function (datasetItem) {
changeVersionOnItem(datasetItem.entityId, datasetItem.versionNumber);
} })));
};
var SelectAllCheckboxRenderer = function (props) {
var datasetToUpdate = props.datasetToUpdate, clearSelectedIds = props.clearSelectedIds, addSelectedId = props.addSelectedId;
(0, useTraceUpdate_1.default)(props);
var isChecked = allItemsAreSelected;
return datasetToUpdate ? (react_1.default.createElement("div", { "data-testid": "Select All", style: { cursor: 'pointer' }, onClick: function () {
if (isChecked) {
clearSelectedIds();
}
else {
addSelectedId.apply(void 0, datasetToUpdate.items.map(function (item) { return item.entityId; }));
}
} },
react_1.default.createElement(Checkbox_1.Checkbox, { label: "", className: "SRC-pointer-events-none", checked: isChecked, disabled: datasetToUpdate.items.length === 0, onChange: function () {
// no-op
} }))) : (react_1.default.createElement(react_1.default.Fragment, null));
};
var renderedSelectAllCheckbox = datasetToUpdate ? (react_1.default.createElement(SelectAllCheckboxRenderer, { datasetToUpdate: datasetToUpdate, selectedIds: selectedIds, clearSelectedIds: clearSelectedIds, addSelectedId: addSelectedId, allItemsAreSelected: allItemsAreSelected })) : (react_1.default.createElement(react_1.default.Fragment, null));
var defaultColumns = [
{
key: 'errorState',
width: 30,
cellRenderer: DetailsViewTableRenderers_1.EntityErrorRenderer,
},
{
key: 'isSelected',
width: 40,
dataKey: 'isSelected',
headerRenderer: renderedSelectAllCheckbox,
cellRenderer: DetailsViewTableRenderers_1.DatasetEditorCheckboxRenderer,
},
{
key: 'name',
width: 350,
dataKey: 'entityId',
title: 'Name',
resizable: true,
cellRenderer: DetailsViewTableRenderers_1.EntityNameRenderer,
},
{
key: 'status',
width: 80,
dataKey: 'entityId',
resizable: true,
cellRenderer: DetailsViewTableRenderers_1.BadgeIconsRenderer,
},
{
key: 'id',
width: 140,
title: 'ID',
dataKey: 'entityId',
resizable: true,
},
{
key: 'version',
width: 150,
title: 'Version',
dataKey: 'entityId',
cellRenderer: DatasetItemVersionRenderer,
},
{
key: 'createdOn',
width: 200,
title: 'Created On',
dataKey: 'entityId',
resizable: true,
cellRenderer: DetailsViewTableRenderers_1.CreatedOnRenderer,
},
{
key: 'modifiedOn',
width: 200,
title: 'Modified On',
dataKey: 'entityId',
resizable: true,
cellRenderer: DetailsViewTableRenderers_1.ModifiedOnRenderer,
},
{
key: 'modifiedBy',
width: 250,
title: 'Modified By',
dataKey: 'entityId',
resizable: true,
cellRenderer: DetailsViewTableRenderers_1.ModifiedByRenderer,
},
{
key: 'projectId',
width: 300,
title: 'Project',
dataKey: 'entityId',
resizable: true,
cellRenderer: DetailsViewTableRenderers_1.ProjectRenderer,
},
];
function NoItemsPlaceholder() {
return (react_1.default.createElement("div", { className: "NoItemsPlaceholder" },
react_1.default.createElement(Typography_1.default, { variant: 'headline3' }, "No items in this Dataset"),
react_1.default.createElement(react_bootstrap_1.Button, { className: "AddItemsButton", variant: "outline", onClick: function () { return setShowEntityFinder(true); } },
react_1.default.createElement(IconSvg_1.default, { options: { icon: 'addCircleTwoTone' } }),
react_1.default.createElement("span", null, "Add Items"))));
}
return (react_1.default.createElement("div", { className: "DatasetEditor bootstrap-4-backport" },
react_1.default.createElement(EntityFinderModal_1.EntityFinderModal, { configuration: {
selectMultiple: true,
initialScope: TreeView_1.FinderScope.ALL_PROJECTS,
initialContainer: null,
selectableTypes: [synapseTypes_1.EntityType.FILE],
mustSelectVersionNumber: true,
}, show: showEntityFinder, onClose: function () {
setShowEntityFinder(false);
}, title: "Add Files to Dataset", confirmButtonCopy: "Add Files", onConfirm: function (items) {
addItemsToDataset(items);
setShowEntityFinder(false);
}, onCancel: function () { return setShowEntityFinder(false); } }),
react_1.default.createElement(WarningModal_1.default, { title: "Unsaved Changes", modalBody: "Any unsaved changes will be lost. Are you sure you want to close the editor?", confirmButtonText: "Close Editor", onConfirm: function () {
if (onClose) {
setShowWarningModal(false);
onClose();
}
}, show: showWarningModal, onConfirmCallbackArgs: [], onCancel: function () { return setShowWarningModal(false); } }),
react_1.default.createElement("div", { className: "DatasetEditorTopBottomPanel" },
react_1.default.createElement("div", { className: "ItemCount" }, datasetToUpdate ? (react_1.default.createElement(Typography_1.default, { variant: "headline3" },
datasetToUpdate.items.length === 0
? 'No'
: datasetToUpdate.items.length.toLocaleString(),
' ',
"File",
datasetToUpdate.items.length !== 1 && 's')) : (react_1.default.createElement(lab_1.Skeleton, { variant: "rect", width: 200 }))),
react_1.default.createElement(react_bootstrap_1.Button, { variant: "outline", disabled: datasetToUpdate == null, onClick: function () { return setShowEntityFinder(true); } }, "Add Items"),
react_1.default.createElement(react_bootstrap_1.Button, { disabled: selectedIds.size === 0, variant: "outline", onClick: removeSelectedItemsFromDataset }, "Remove Items")),
react_1.default.createElement("div", { className: "DatasetEditorTableContainer" },
datasetToUpdate ? (datasetToUpdate.items.length === 0 ? (react_1.default.createElement(NoItemsPlaceholder, null)) : (react_1.default.createElement(react_base_table_1.default, { classPrefix: "DatasetEditorTable", data: tableData, height: TABLE_HEIGHT, width: defaultColumns.reduce(function (totalWidth, column) {
return totalWidth + column.width;
}, 0), rowHeight: ROW_HEIGHT, overscanRowCount: 5, columns: defaultColumns, rowClassName: 'DatasetEditorRow', rowProps: function (_a) {
var rowData = _a.rowData;
return {
'aria-selected': rowData.isSelected,
};
}, headerCellProps: {
role: 'columnheader',
}, onRowsRendered: TooltipUtils_1.rebuildTooltip, onScroll: TooltipUtils_1.rebuildTooltip }))) : (react_1.default.createElement(SkeletonTable_1.SkeletonTable, { className: "DatasetItemsEditorSkeleton", numRows: 8, numCols: 6, rowHeight: ROW_HEIGHT + "px" })),
react_1.default.createElement(react_tooltip_1.default, { id: EntityBadgeIcons_1.ENTITY_BADGE_ICONS_TOOLTIP_ID, className: "EntityBadgeTooltip", delayShow: 100, place: 'right', effect: 'solid' })),
react_1.default.createElement("div", { className: "DatasetEditorTopBottomPanel" },
react_1.default.createElement(react_bootstrap_1.Button, { variant: 'outline', onClick: function () {
if (hasChangedSinceLastSave) {
setShowWarningModal(true);
}
else if (onClose) {
onClose();
}
} }, "Cancel"),
react_1.default.createElement(react_bootstrap_1.Button, { disabled: !datasetToUpdate, variant: 'sds-primary', onClick: function () { return mutation.mutate(datasetToUpdate); } }, "Save"))));
}
exports.DatasetItemsEditor = DatasetItemsEditor;
//# sourceMappingURL=DatasetItemsEditor.js.map