@jupyterlab/git
Version:
A JupyterLab extension for version control using git
102 lines (101 loc) • 6.37 kB
JavaScript
import { caretDownIcon, caretRightIcon } from '@jupyterlab/ui-components';
import * as React from 'react';
import { changeStageButtonStyle, sectionAreaStyle, sectionFileContainerStyle } from '../style/GitStageStyle';
import { hiddenButtonStyle } from '../style/ActionButtonStyle';
import { ActionButton } from './ActionButton';
import { addIcon, trashIcon, discardIcon } from '../style/icons';
import { UseSignal } from '@jupyterlab/apputils';
import { FixedSizeList } from 'react-window';
import { listStyle, sectionButtonContainerStyle, sectionHeaderLabelStyle, stashFileStyle, stashEntryMessageStyle, stashContainerStyle } from '../style/GitStashStyle';
import { FilePath } from './FilePath';
import { stopPropagationWrapper } from '../utils';
import { classes } from 'typestyle';
const HEADER_HEIGHT = 34;
const ITEM_HEIGHT = 25;
/**
* Dropdown for each entry in the stash
*/
const GitStashEntry = (props) => {
const [showStashFiles, setShowStashFiles] = React.useState(false);
const nFiles = props.files.length;
return (React.createElement("div", { className: sectionFileContainerStyle },
React.createElement("div", { className: sectionAreaStyle, onClick: () => {
if (props.collapsible && (props === null || props === void 0 ? void 0 : props.files.length) > 0) {
setShowStashFiles(!showStashFiles);
}
} },
props.collapsible && (React.createElement("button", { className: changeStageButtonStyle }, showStashFiles && (props === null || props === void 0 ? void 0 : props.files.length) > 0 ? (React.createElement(caretDownIcon.react, { tag: "span" })) : (React.createElement(caretRightIcon.react, { tag: "span" })))),
React.createElement("span", { className: sectionHeaderLabelStyle },
React.createElement("span", { className: stashEntryMessageStyle }, props.trans.__('%1 (on %2)', props.message, props.branch)),
React.createElement("span", { className: sectionButtonContainerStyle }, props.actions))),
showStashFiles && (React.createElement(FixedSizeList, { className: listStyle, height: Math.max(Math.min(props.height - HEADER_HEIGHT, nFiles * ITEM_HEIGHT), ITEM_HEIGHT), itemCount: nFiles, innerElementType: "ul", itemData: props === null || props === void 0 ? void 0 : props.files, itemKey: (index, data) => data[index], itemSize: ITEM_HEIGHT, width: 'auto', style: { margin: 0, paddingLeft: 0 } }, ({ index }) => {
const file = props.files[index];
return (React.createElement("li", { className: stashFileStyle },
React.createElement(FilePath, { filepath: file })));
}))));
};
export const GitStash = (props) => {
var _a, _b;
const [showStash, setShowStash] = React.useState(false);
const [stashIsLoading, setStashIsLoading] = React.useState(true);
const nStash = (_b = (_a = props.stash) === null || _a === void 0 ? void 0 : _a.length) !== null && _b !== void 0 ? _b : 0;
const gitStashPop = React.useCallback(async (index) => {
try {
await props.model.popStash(index);
}
catch (err) {
console.error(err);
}
}, [props.model]);
const gitStashDrop = React.useCallback(async (index) => {
try {
await props.model.dropStash(index);
}
catch (err) {
console.error(err);
}
}, [props.model]);
const gitStashApply = React.useCallback(async (index) => {
try {
await props.model.applyStash(index);
}
catch (err) {
console.error(err);
}
}, [props.model]);
return (React.createElement("div", { className: classes(sectionFileContainerStyle, stashContainerStyle) },
React.createElement("div", { className: sectionAreaStyle, onClick: () => {
if (props.collapsible && nStash > 0) {
setShowStash(!showStash);
}
} },
props.selectAllButton && props.selectAllButton,
props.collapsible && (React.createElement("button", { className: changeStageButtonStyle }, showStash && nStash > 0 ? (React.createElement(caretDownIcon.react, { tag: "span" })) : (React.createElement(caretRightIcon.react, { tag: "span" })))),
React.createElement("span", { className: sectionHeaderLabelStyle },
React.createElement("span", null, props.trans.__('Stash')),
React.createElement("span", { className: sectionButtonContainerStyle },
props.actions,
React.createElement("span", { "data-test-id": "num-stashes", "data-loading": stashIsLoading ? 'true' : 'false' },
"(",
nStash,
")")))),
React.createElement(UseSignal, { signal: props.model.stashChanged }, () => {
if (!props.stash || !Array.isArray(props.stash)) {
return null;
}
const nStash = props.stash.length;
setStashIsLoading(false);
return (props.model.stashChanged &&
showStash &&
nStash > 0 && (React.createElement(React.Fragment, null, props.stash.map(entry => (React.createElement(GitStashEntry, { key: entry.index, files: entry.files, model: props.model, index: entry.index, branch: entry.branch, trans: props.trans, message: entry.message, height: 100, collapsible: true, actions: React.createElement(React.Fragment, null,
React.createElement(ActionButton, { className: hiddenButtonStyle, icon: discardIcon, title: props.trans.__('Pop stash entry'), onClick: stopPropagationWrapper(() => {
gitStashPop(entry.index);
}) }),
React.createElement(ActionButton, { className: hiddenButtonStyle, icon: addIcon, title: props.trans.__('Apply stash entry'), onClick: stopPropagationWrapper(() => {
gitStashApply(entry.index);
}) }),
React.createElement(ActionButton, { className: hiddenButtonStyle, icon: trashIcon, title: props.trans.__('Drop stash entry'), onClick: stopPropagationWrapper(() => {
gitStashDrop(entry.index);
}) })) }))))));
})));
};