UNPKG

@jupyterlab/git

Version:

A JupyterLab extension for version control using git

107 lines (106 loc) 7.04 kB
import { caretDownIcon } from '@jupyterlab/ui-components'; import * as React from 'react'; import { changeStageButtonStyle, sectionAreaStyle, sectionFileContainerStyle, sectionHeaderSizeStyle } 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, stashFileStyle, stashEntryMessageStyle, stashContainerStyle } from '../style/GitStashStyle'; import { FilePath } from './FilePath'; import { stopPropagation, 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) => { var _a; const [showStashFiles, setShowStashFiles] = React.useState(false); const nFiles = props.files.length; const canToggle = ((_a = props.collapsible) !== null && _a !== void 0 ? _a : false) && nFiles > 0; const onToggle = () => { if (canToggle) { setShowStashFiles(!showStashFiles); } }; const stashEntryLabel = props.trans.__('%1 (on %2)', props.message, props.branch); return (React.createElement("div", { className: sectionFileContainerStyle }, React.createElement("div", { className: classes('jp-AccordionPanel-title', showStashFiles && nFiles > 0 ? 'lm-mod-expanded' : null, sectionAreaStyle), onClick: onToggle }, props.collapsible && (React.createElement("button", { type: "button", className: classes('lm-AccordionPanel-titleCollapser', changeStageButtonStyle), "aria-expanded": canToggle ? showStashFiles : undefined, "aria-label": stashEntryLabel, disabled: !canToggle }, React.createElement(caretDownIcon.react, { tag: "span" }))), React.createElement("span", { className: "lm-AccordionPanel-titleLabel" }, React.createElement("span", { className: stashEntryMessageStyle }, stashEntryLabel)), props.actions && (React.createElement("div", { className: classes('jp-AccordionPanel-toolbar', sectionButtonContainerStyle), onClick: stopPropagation }, 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, _c; 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 canToggle = ((_c = props.collapsible) !== null && _c !== void 0 ? _c : false) && nStash > 0; const onToggle = () => { if (canToggle) { setShowStash(!showStash); } }; const stashLabel = props.trans.__('Stash'); 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: classes('jp-AccordionPanel-title', showStash && nStash > 0 ? 'lm-mod-expanded' : null, sectionAreaStyle), onClick: onToggle }, props.selectAllButton && (React.createElement("span", { style: { display: 'contents' }, onClick: stopPropagation }, props.selectAllButton)), props.collapsible && (React.createElement("button", { type: "button", className: classes('lm-AccordionPanel-titleCollapser', changeStageButtonStyle), "aria-expanded": canToggle ? showStash : undefined, "aria-label": stashLabel, disabled: !canToggle }, React.createElement(caretDownIcon.react, { tag: "span" }))), React.createElement("span", { className: "lm-AccordionPanel-titleLabel" }, stashLabel), React.createElement("div", { className: classes('jp-AccordionPanel-toolbar', sectionButtonContainerStyle), onClick: stopPropagation }, props.actions, React.createElement("span", { className: nStash > 0 ? sectionHeaderSizeStyle : undefined, "data-test-id": "num-stashes", "data-loading": stashIsLoading ? 'true' : 'false' }, nStash > 0 ? 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); }) })) })))))); }))); };