-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathGitNode.tsx
134 lines (124 loc) · 3.91 KB
/
GitNode.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
import {clipboard, isDefined} from '#preload';
import {styled} from '@mui/material';
import type {Color} from '@syn-types/app';
import type {Prettify} from '@syn-types/util';
import {useMemo, useState, type MouseEvent} from 'react';
import {Handle, Position, type NodeProps} from 'reactflow';
import type {CommitVertex} from '../../containers/hooks/useGitGraph';
import useToggle from '../../containers/hooks/useToggle';
import {useAppSelector} from '../../store/hooks';
import branchSelectors from '../../store/selectors/branches';
import ContextMenu from './ContextMenu';
import GraphTooltip from './GraphTooltip';
export type GitNodeProps = Prettify<NodeProps<CommitVertex>>;
const GitNode = (props: GitNodeProps) => {
const branches = useAppSelector(state => branchSelectors.selectEntities(state));
const [isHovering, toggleHovering] = useToggle(false);
const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleMenu = (event: MouseEvent<HTMLDivElement>) => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const headText = () => {
const firstHead = props.data.heads[0];
if (firstHead) {
const additional = props.data.heads.length - 1;
const firstBranch = branches[firstHead];
return `${firstBranch?.scope}/${firstBranch?.ref}${additional > 0 ? ` + ${additional}` : ''}`;
}
return undefined;
};
const text = props.data.heads.length > 0 ? headText() : props.data.oid.toString();
const tooltip = useMemo((): string => {
const commit = props.data;
const headBranches = commit.heads.map(oid => branches[oid]).filter(isDefined);
return `${
headBranches.length > 0
? `Branches: ${headBranches.map(branch => `${branch.scope}/${branch.ref}`).join(',')}\n`
: ''
}Commit: ${commit.oid.toString()}\nParent: ${commit.parents.join(', ')}\nAuthor: ${
commit.author.name
} <${commit.author.email}>\nMessage: ${commit.message}`;
}, [branches, props.data]);
const color = props.data.color;
const borderColor = props.selected ? '#F08080' : 'whitesmoke';
const borderStyle = props.selected ? 'solid' : props.data.staged ? 'dashed' : '';
const opacity = props.data.staged ? '0.6' : '1.0';
const copyToClipboard = (text: string) => {
clipboard.writeText(text);
};
return (
<>
<GraphTooltip
disabled={!isHovering}
content={tooltip}
placement="bottom"
/>
<Node
color={color}
borderStyle={borderStyle}
borderColor={borderColor}
opacity={opacity}
onMouseEnter={() => toggleHovering(true)}
onMouseLeave={() => toggleHovering(false)}
onClick={() => {
copyToClipboard(props.id);
const node = props.data;
console.log(node);
}}
onContextMenu={handleMenu}
>
<StyledHandle
type="target"
position={Position.Top}
/>
<StyledHandle
type="source"
position={Position.Bottom}
/>
</Node>
<StyledText>{text}</StyledText>
<ContextMenu
open={open}
anchorEl={anchorEl}
node={props}
onClose={handleClose}
/>
</>
);
};
const Node = styled('div')<{
color: Color;
borderStyle: string;
borderColor: string;
opacity?: string | undefined;
}>(props => ({
width: 10,
borderRadius: '50%',
margin: 'auto',
borderStyle: props.borderStyle,
borderColor: props.borderColor,
borderWidth: 'thin',
opacity: props.opacity,
background: props.color,
padding: 5,
}));
const StyledHandle = styled(Handle)(() => ({
visibility: 'hidden',
}));
const StyledText = styled('div')(() => ({
color: 'whitesmoke',
fontSize: 6,
width: 50,
textAlign: 'center',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
overflow: 'hidden',
}));
export const nodeTypes = {
gitNode: GitNode,
};
export default GitNode;