UNPKG

@jupyterlab/git

Version:

A JupyterLab extension for version control using git

102 lines (101 loc) 6.37 kB
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); }) })) })))))); }))); };