@stoked-ui/github 0.0.0-a.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15014 -0
- package/GithubCalendar/GithubCalendar.d.ts +7 -0
- package/GithubCalendar/GithubCalendar.js +330 -0
- package/GithubCalendar/index.d.ts +2 -0
- package/GithubCalendar/index.js +2 -0
- package/GithubCalendar/package.json +6 -0
- package/GithubEvents/EventTypes/CreateEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/CreateEvent.js +72 -0
- package/GithubEvents/EventTypes/DeleteEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/DeleteEvent.js +65 -0
- package/GithubEvents/EventTypes/ForkEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/ForkEvent.js +77 -0
- package/GithubEvents/EventTypes/IssueCommentEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/IssueCommentEvent.js +210 -0
- package/GithubEvents/EventTypes/IssuesEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/IssuesEvent.js +97 -0
- package/GithubEvents/EventTypes/ProjectsV2ColumnEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/ProjectsV2ColumnEvent.js +69 -0
- package/GithubEvents/EventTypes/ProjectsV2Event.d.ts +7 -0
- package/GithubEvents/EventTypes/ProjectsV2Event.js +74 -0
- package/GithubEvents/EventTypes/ProjectsV2FieldEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/ProjectsV2FieldEvent.js +77 -0
- package/GithubEvents/EventTypes/ProjectsV2ItemEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/ProjectsV2ItemEvent.js +79 -0
- package/GithubEvents/EventTypes/PullRequest/CommitsList.d.ts +17 -0
- package/GithubEvents/EventTypes/PullRequest/CommitsList.js +99 -0
- package/GithubEvents/EventTypes/PullRequest/FileChanges.d.ts +17 -0
- package/GithubEvents/EventTypes/PullRequest/FileChanges.js +182 -0
- package/GithubEvents/EventTypes/PullRequest/PullRequestEvent.d.ts +8 -0
- package/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +374 -0
- package/GithubEvents/EventTypes/PullRequest/PullRequestView.d.ts +29 -0
- package/GithubEvents/EventTypes/PullRequest/PullRequestView.js +132 -0
- package/GithubEvents/EventTypes/PushEvent.d.ts +7 -0
- package/GithubEvents/EventTypes/PushEvent.js +106 -0
- package/GithubEvents/GithubEvents.d.ts +49 -0
- package/GithubEvents/GithubEvents.js +1454 -0
- package/GithubEvents/index.d.ts +2 -0
- package/GithubEvents/index.js +2 -0
- package/GithubEvents/package.json +6 -0
- package/LICENSE +21 -0
- package/README.md +29 -0
- package/apiHandlers/getPullRequestDetails.d.ts +7 -0
- package/apiHandlers/getPullRequestDetails.js +120 -0
- package/apiHandlers/index.d.ts +1 -0
- package/apiHandlers/index.js +1 -0
- package/apiHandlers/package.json +6 -0
- package/index.d.ts +3 -0
- package/index.js +10 -0
- package/modern/GithubCalendar/GithubCalendar.js +330 -0
- package/modern/GithubCalendar/index.js +2 -0
- package/modern/GithubEvents/EventTypes/CreateEvent.js +72 -0
- package/modern/GithubEvents/EventTypes/DeleteEvent.js +65 -0
- package/modern/GithubEvents/EventTypes/ForkEvent.js +77 -0
- package/modern/GithubEvents/EventTypes/IssueCommentEvent.js +210 -0
- package/modern/GithubEvents/EventTypes/IssuesEvent.js +97 -0
- package/modern/GithubEvents/EventTypes/ProjectsV2ColumnEvent.js +69 -0
- package/modern/GithubEvents/EventTypes/ProjectsV2Event.js +74 -0
- package/modern/GithubEvents/EventTypes/ProjectsV2FieldEvent.js +77 -0
- package/modern/GithubEvents/EventTypes/ProjectsV2ItemEvent.js +79 -0
- package/modern/GithubEvents/EventTypes/PullRequest/CommitsList.js +99 -0
- package/modern/GithubEvents/EventTypes/PullRequest/FileChanges.js +182 -0
- package/modern/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +374 -0
- package/modern/GithubEvents/EventTypes/PullRequest/PullRequestView.js +132 -0
- package/modern/GithubEvents/EventTypes/PushEvent.js +106 -0
- package/modern/GithubEvents/GithubEvents.js +1454 -0
- package/modern/GithubEvents/index.js +2 -0
- package/modern/apiHandlers/getPullRequestDetails.js +120 -0
- package/modern/apiHandlers/index.js +1 -0
- package/modern/index.js +10 -0
- package/modern/types/github.js +1 -0
- package/node/GithubCalendar/GithubCalendar.js +337 -0
- package/node/GithubCalendar/index.js +9 -0
- package/node/GithubEvents/EventTypes/CreateEvent.js +80 -0
- package/node/GithubEvents/EventTypes/DeleteEvent.js +73 -0
- package/node/GithubEvents/EventTypes/ForkEvent.js +85 -0
- package/node/GithubEvents/EventTypes/IssueCommentEvent.js +218 -0
- package/node/GithubEvents/EventTypes/IssuesEvent.js +105 -0
- package/node/GithubEvents/EventTypes/ProjectsV2ColumnEvent.js +77 -0
- package/node/GithubEvents/EventTypes/ProjectsV2Event.js +82 -0
- package/node/GithubEvents/EventTypes/ProjectsV2FieldEvent.js +85 -0
- package/node/GithubEvents/EventTypes/ProjectsV2ItemEvent.js +87 -0
- package/node/GithubEvents/EventTypes/PullRequest/CommitsList.js +107 -0
- package/node/GithubEvents/EventTypes/PullRequest/FileChanges.js +188 -0
- package/node/GithubEvents/EventTypes/PullRequest/PullRequestEvent.js +381 -0
- package/node/GithubEvents/EventTypes/PullRequest/PullRequestView.js +138 -0
- package/node/GithubEvents/EventTypes/PushEvent.js +114 -0
- package/node/GithubEvents/GithubEvents.js +1463 -0
- package/node/GithubEvents/index.js +9 -0
- package/node/apiHandlers/getPullRequestDetails.js +127 -0
- package/node/apiHandlers/index.js +13 -0
- package/node/index.js +27 -0
- package/node/types/github.js +5 -0
- package/package.json +71 -0
- package/types/github.d.ts +107 -0
- package/types/github.js +1 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
var _CopyIcon, _CheckoutIcon;
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import Box from '@mui/material/Box';
|
|
4
|
+
import Typography from '@mui/material/Typography';
|
|
5
|
+
import Avatar from '@mui/material/Avatar';
|
|
6
|
+
import IconButton from '@mui/material/IconButton';
|
|
7
|
+
import { styled } from '@mui/material/styles';
|
|
8
|
+
import CopyIcon from '@mui/icons-material/ContentCopy';
|
|
9
|
+
import CheckoutIcon from '@mui/icons-material/CallMade';
|
|
10
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
11
|
+
const CommitItem = styled(Box)(({
|
|
12
|
+
theme
|
|
13
|
+
}) => ({
|
|
14
|
+
display: 'flex',
|
|
15
|
+
alignItems: 'flex-start',
|
|
16
|
+
padding: theme.spacing(2),
|
|
17
|
+
borderBottom: `1px solid ${theme.palette.divider}`,
|
|
18
|
+
'&:last-child': {
|
|
19
|
+
borderBottom: 'none'
|
|
20
|
+
},
|
|
21
|
+
'&:hover': {
|
|
22
|
+
backgroundColor: theme.palette.action.hover,
|
|
23
|
+
'.commit-actions': {
|
|
24
|
+
visibility: 'visible'
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}));
|
|
28
|
+
const CommitActions = styled(Box)({
|
|
29
|
+
visibility: 'hidden',
|
|
30
|
+
display: 'flex',
|
|
31
|
+
gap: '8px'
|
|
32
|
+
});
|
|
33
|
+
export default function CommitsList({
|
|
34
|
+
commits,
|
|
35
|
+
onCheckout
|
|
36
|
+
}) {
|
|
37
|
+
const handleCopyHash = hash => {
|
|
38
|
+
navigator.clipboard.writeText(hash);
|
|
39
|
+
};
|
|
40
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
41
|
+
children: commits.map(commit => /*#__PURE__*/_jsx(CommitItem, {
|
|
42
|
+
children: /*#__PURE__*/_jsxs(Box, {
|
|
43
|
+
sx: {
|
|
44
|
+
display: 'flex',
|
|
45
|
+
width: '100%'
|
|
46
|
+
},
|
|
47
|
+
children: [/*#__PURE__*/_jsx(Avatar, {
|
|
48
|
+
src: commit.author.avatar,
|
|
49
|
+
alt: commit.author.name,
|
|
50
|
+
sx: {
|
|
51
|
+
width: 32,
|
|
52
|
+
height: 32,
|
|
53
|
+
mr: 2
|
|
54
|
+
}
|
|
55
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
56
|
+
sx: {
|
|
57
|
+
flex: 1
|
|
58
|
+
},
|
|
59
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
60
|
+
variant: "body1",
|
|
61
|
+
sx: {
|
|
62
|
+
mb: 0.5,
|
|
63
|
+
wordBreak: 'break-word'
|
|
64
|
+
},
|
|
65
|
+
children: commit.message
|
|
66
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
67
|
+
sx: {
|
|
68
|
+
display: 'flex',
|
|
69
|
+
alignItems: 'center',
|
|
70
|
+
justifyContent: 'space-between'
|
|
71
|
+
},
|
|
72
|
+
children: [/*#__PURE__*/_jsxs(Typography, {
|
|
73
|
+
variant: "body2",
|
|
74
|
+
color: "text.secondary",
|
|
75
|
+
children: [commit.author.name, " committed ", commit.date]
|
|
76
|
+
}), /*#__PURE__*/_jsxs(CommitActions, {
|
|
77
|
+
className: "commit-actions",
|
|
78
|
+
children: [/*#__PURE__*/_jsx(IconButton, {
|
|
79
|
+
size: "small",
|
|
80
|
+
onClick: () => handleCopyHash(commit.hash),
|
|
81
|
+
title: "Copy commit SHA",
|
|
82
|
+
children: _CopyIcon || (_CopyIcon = /*#__PURE__*/_jsx(CopyIcon, {
|
|
83
|
+
fontSize: "small"
|
|
84
|
+
}))
|
|
85
|
+
}), /*#__PURE__*/_jsx(IconButton, {
|
|
86
|
+
size: "small",
|
|
87
|
+
onClick: () => onCheckout == null ? void 0 : onCheckout(commit.hash),
|
|
88
|
+
title: "Checkout commit",
|
|
89
|
+
children: _CheckoutIcon || (_CheckoutIcon = /*#__PURE__*/_jsx(CheckoutIcon, {
|
|
90
|
+
fontSize: "small"
|
|
91
|
+
}))
|
|
92
|
+
})]
|
|
93
|
+
})]
|
|
94
|
+
})]
|
|
95
|
+
})]
|
|
96
|
+
})
|
|
97
|
+
}, commit.id))
|
|
98
|
+
});
|
|
99
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface FileChange {
|
|
3
|
+
path: string;
|
|
4
|
+
type: 'added' | 'modified' | 'deleted';
|
|
5
|
+
additions: number;
|
|
6
|
+
deletions: number;
|
|
7
|
+
diff: Array<{
|
|
8
|
+
type: 'addition' | 'deletion' | 'context';
|
|
9
|
+
content: string;
|
|
10
|
+
lineNumber: number;
|
|
11
|
+
}>;
|
|
12
|
+
}
|
|
13
|
+
interface FileChangesProps {
|
|
14
|
+
files: FileChange[];
|
|
15
|
+
}
|
|
16
|
+
export default function FileChanges({ files }: FileChangesProps): React.JSX.Element;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
2
|
+
var _Chip, _Chip2, _Chip3, _FileIcon;
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import Box from '@mui/material/Box';
|
|
5
|
+
import Typography from '@mui/material/Typography';
|
|
6
|
+
import { SimpleTreeView } from '@mui/x-tree-view/SimpleTreeView';
|
|
7
|
+
import { TreeItem } from '@mui/x-tree-view/TreeItem';
|
|
8
|
+
import { styled } from '@mui/material/styles';
|
|
9
|
+
// import FolderIcon from '@mui/icons-material/Folder';
|
|
10
|
+
import FileIcon from '@mui/icons-material/InsertDriveFile';
|
|
11
|
+
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
|
12
|
+
import ExpandMoreIcon from '@mui/icons-material/ExpandMore';
|
|
13
|
+
import Chip from '@mui/material/Chip';
|
|
14
|
+
|
|
15
|
+
// const StyledTreeItem = styled(TreeItem)((props) => ({
|
|
16
|
+
// '& .MuiTreeItem-content': {
|
|
17
|
+
// padding: props.theme.spacing(1),
|
|
18
|
+
// borderRadius: props.theme.shape.borderRadius,
|
|
19
|
+
// '&:hover': {
|
|
20
|
+
// backgroundColor: props.theme.palette.action.hover,
|
|
21
|
+
// },
|
|
22
|
+
// '& .MuiTreeItem-label': {
|
|
23
|
+
// display: 'flex',
|
|
24
|
+
// alignItems: 'center',
|
|
25
|
+
// gap: props.theme.spacing(1),
|
|
26
|
+
// },
|
|
27
|
+
// },
|
|
28
|
+
// }));
|
|
29
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
30
|
+
const DiffView = styled(Box)(({
|
|
31
|
+
theme
|
|
32
|
+
}) => ({
|
|
33
|
+
backgroundColor: theme.palette.background.paper,
|
|
34
|
+
border: `1px solid ${theme.palette.divider}`,
|
|
35
|
+
borderRadius: theme.shape.borderRadius,
|
|
36
|
+
fontFamily: 'ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace',
|
|
37
|
+
fontSize: '12px',
|
|
38
|
+
lineHeight: 1.5,
|
|
39
|
+
overflow: 'auto'
|
|
40
|
+
}));
|
|
41
|
+
const DiffLine = styled(Box, {
|
|
42
|
+
shouldForwardProp: prop => prop !== 'type'
|
|
43
|
+
})(({
|
|
44
|
+
theme,
|
|
45
|
+
type
|
|
46
|
+
}) => _extends({
|
|
47
|
+
padding: '0 16px',
|
|
48
|
+
whiteSpace: 'pre'
|
|
49
|
+
}, type === 'addition' && {
|
|
50
|
+
backgroundColor: 'rgba(46, 160, 67, 0.15)',
|
|
51
|
+
borderLeft: '4px solid #2ea043'
|
|
52
|
+
}, type === 'deletion' && {
|
|
53
|
+
backgroundColor: 'rgba(248, 81, 73, 0.15)',
|
|
54
|
+
borderLeft: '4px solid #f85149'
|
|
55
|
+
}, type === 'context' && {
|
|
56
|
+
backgroundColor: 'transparent',
|
|
57
|
+
borderLeft: '4px solid transparent'
|
|
58
|
+
}));
|
|
59
|
+
// interface TreeNode {
|
|
60
|
+
// id: string;
|
|
61
|
+
// name: string;
|
|
62
|
+
// type: FileChange['type'];
|
|
63
|
+
// additions: number;
|
|
64
|
+
// deletions: number;
|
|
65
|
+
// diff: FileChange['diff'];
|
|
66
|
+
// children?: TreeNode[];
|
|
67
|
+
// }
|
|
68
|
+
|
|
69
|
+
export default function FileChanges({
|
|
70
|
+
files
|
|
71
|
+
}) {
|
|
72
|
+
const [expanded, setExpanded] = React.useState([]);
|
|
73
|
+
const [selected, setSelected] = React.useState([]);
|
|
74
|
+
const handleToggle = (_event, nodeIds) => {
|
|
75
|
+
setExpanded(nodeIds);
|
|
76
|
+
};
|
|
77
|
+
const handleSelect = (_event, nodeIds) => {
|
|
78
|
+
setSelected(nodeIds);
|
|
79
|
+
};
|
|
80
|
+
const getFileIcon = type => {
|
|
81
|
+
switch (type) {
|
|
82
|
+
case 'added':
|
|
83
|
+
return _Chip || (_Chip = /*#__PURE__*/_jsx(Chip, {
|
|
84
|
+
label: "A",
|
|
85
|
+
size: "small",
|
|
86
|
+
color: "success"
|
|
87
|
+
}));
|
|
88
|
+
case 'modified':
|
|
89
|
+
return _Chip2 || (_Chip2 = /*#__PURE__*/_jsx(Chip, {
|
|
90
|
+
label: "M",
|
|
91
|
+
size: "small",
|
|
92
|
+
color: "warning"
|
|
93
|
+
}));
|
|
94
|
+
case 'deleted':
|
|
95
|
+
return _Chip3 || (_Chip3 = /*#__PURE__*/_jsx(Chip, {
|
|
96
|
+
label: "D",
|
|
97
|
+
size: "small",
|
|
98
|
+
color: "error"
|
|
99
|
+
}));
|
|
100
|
+
default:
|
|
101
|
+
return _FileIcon || (_FileIcon = /*#__PURE__*/_jsx(FileIcon, {}));
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// Transform files into tree nodes
|
|
106
|
+
// const items: TreeNode[] = files.map((file, index) => ({
|
|
107
|
+
// id: `file-${index}-${file.path.replace(/[^a-zA-Z0-9]/g, '-')}`,
|
|
108
|
+
// name: file.path,
|
|
109
|
+
// type: file.type,
|
|
110
|
+
// additions: file.additions,
|
|
111
|
+
// deletions: file.deletions,
|
|
112
|
+
// diff: file.diff
|
|
113
|
+
// }));
|
|
114
|
+
|
|
115
|
+
// const renderLabel = (node: TreeNode) => (
|
|
116
|
+
// <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
|
117
|
+
// {getFileIcon(node.type)}
|
|
118
|
+
// <Typography variant="body2">{node.name}</Typography>
|
|
119
|
+
// <Typography variant="caption" color="text.secondary">
|
|
120
|
+
// +{node.additions} -{node.deletions}
|
|
121
|
+
// </Typography>
|
|
122
|
+
// </Box>
|
|
123
|
+
// );
|
|
124
|
+
|
|
125
|
+
// const renderContent = (node: TreeNode) => (
|
|
126
|
+
// <Box sx={{ p: '16px' }}>
|
|
127
|
+
// <DiffView>
|
|
128
|
+
// {node.diff.map((line, index) => (
|
|
129
|
+
// <DiffLine key={`${node.id}-line-${index}`} type={line.type}>
|
|
130
|
+
// {line.content}
|
|
131
|
+
// </DiffLine>
|
|
132
|
+
// ))}
|
|
133
|
+
// </DiffView>
|
|
134
|
+
// </Box>
|
|
135
|
+
// );
|
|
136
|
+
|
|
137
|
+
return /*#__PURE__*/_jsx(Box, {
|
|
138
|
+
children: /*#__PURE__*/_jsx(SimpleTreeView, {
|
|
139
|
+
slots: {
|
|
140
|
+
collapseIcon: ExpandMoreIcon,
|
|
141
|
+
expandIcon: ChevronRightIcon
|
|
142
|
+
},
|
|
143
|
+
expandedItems: expanded,
|
|
144
|
+
selectedItems: selected,
|
|
145
|
+
onExpandedItemsChange: handleToggle,
|
|
146
|
+
onSelectedItemsChange: handleSelect,
|
|
147
|
+
multiSelect: true,
|
|
148
|
+
children: files.map((file, index) => {
|
|
149
|
+
const itemId = `file-${index}-${file.path.replace(/[^a-zA-Z0-9]/g, '-')}`;
|
|
150
|
+
return /*#__PURE__*/_jsx(TreeItem, {
|
|
151
|
+
itemId: itemId,
|
|
152
|
+
label: /*#__PURE__*/_jsxs(Box, {
|
|
153
|
+
sx: {
|
|
154
|
+
display: 'flex',
|
|
155
|
+
alignItems: 'center',
|
|
156
|
+
gap: 1
|
|
157
|
+
},
|
|
158
|
+
children: [getFileIcon(file.type), /*#__PURE__*/_jsx(Typography, {
|
|
159
|
+
variant: "body2",
|
|
160
|
+
children: file.path
|
|
161
|
+
}), /*#__PURE__*/_jsxs(Typography, {
|
|
162
|
+
variant: "caption",
|
|
163
|
+
color: "text.secondary",
|
|
164
|
+
children: ["+", file.additions, " -", file.deletions]
|
|
165
|
+
})]
|
|
166
|
+
}),
|
|
167
|
+
children: /*#__PURE__*/_jsx(Box, {
|
|
168
|
+
sx: {
|
|
169
|
+
p: '16px'
|
|
170
|
+
},
|
|
171
|
+
children: /*#__PURE__*/_jsx(DiffView, {
|
|
172
|
+
children: file.diff.map((line, index) => /*#__PURE__*/_jsx(DiffLine, {
|
|
173
|
+
type: line.type,
|
|
174
|
+
children: line.content
|
|
175
|
+
}, `${itemId}-line-${index}`))
|
|
176
|
+
})
|
|
177
|
+
})
|
|
178
|
+
}, itemId);
|
|
179
|
+
})
|
|
180
|
+
})
|
|
181
|
+
});
|
|
182
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { EventDetails } from '../../../types/github';
|
|
3
|
+
interface PullRequestEventProps {
|
|
4
|
+
event: EventDetails;
|
|
5
|
+
apiUrl?: string;
|
|
6
|
+
}
|
|
7
|
+
export default function PullRequestEvent({ event, apiUrl }: PullRequestEventProps): React.JSX.Element | null;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
var _CheckoutIcon, _Typography2, _Typography3, _CircularProgress;
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import Box from '@mui/material/Box';
|
|
4
|
+
import Typography from '@mui/material/Typography';
|
|
5
|
+
import Link from '@mui/material/Link';
|
|
6
|
+
import Chip from '@mui/material/Chip';
|
|
7
|
+
import CircularProgress from '@mui/material/CircularProgress';
|
|
8
|
+
import Avatar from '@mui/material/Avatar';
|
|
9
|
+
// import Stack from '@mui/material/Stack';
|
|
10
|
+
import Button from '@mui/material/Button';
|
|
11
|
+
import CheckoutIcon from '@mui/icons-material/CallMade';
|
|
12
|
+
import PullRequestView from './PullRequestView';
|
|
13
|
+
import { getPullRequestDetails } from 'packages/sui-github/src/apiHandlers';
|
|
14
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
15
|
+
async function getPRDetails({
|
|
16
|
+
apiUrl,
|
|
17
|
+
params
|
|
18
|
+
}) {
|
|
19
|
+
if (apiUrl) {
|
|
20
|
+
const response = await fetch(`${apiUrl}?owner=${params.owner}&repo=${params.repo}&pull_number=${params.pull_number}`);
|
|
21
|
+
if (!response.ok) {
|
|
22
|
+
throw new Error('Failed to fetch PR details');
|
|
23
|
+
}
|
|
24
|
+
return response.json();
|
|
25
|
+
}
|
|
26
|
+
return getPullRequestDetails(params);
|
|
27
|
+
}
|
|
28
|
+
export default function PullRequestEvent({
|
|
29
|
+
event,
|
|
30
|
+
apiUrl
|
|
31
|
+
}) {
|
|
32
|
+
var _event$payload, _event$payload2, _pullRequest$base, _pullRequest$head, _pullRequest$user, _pullRequest$user2, _Typography, _Chip, _Chip2;
|
|
33
|
+
const [loading, setLoading] = React.useState(true);
|
|
34
|
+
const [prDetails, setPrDetails] = React.useState(null);
|
|
35
|
+
const [error, setError] = React.useState(null);
|
|
36
|
+
|
|
37
|
+
// Use a ref to track if we've already loaded data for this PR
|
|
38
|
+
const requestIdRef = React.useRef(null);
|
|
39
|
+
const currentRequestId = `${event.repo}-${(_event$payload = event.payload) == null || (_event$payload = _event$payload.pull_request) == null ? void 0 : _event$payload.number}`;
|
|
40
|
+
|
|
41
|
+
// Prevent navigation only from anchors in the title and buttons
|
|
42
|
+
const handleLinkClick = e => {
|
|
43
|
+
e.preventDefault();
|
|
44
|
+
e.stopPropagation();
|
|
45
|
+
|
|
46
|
+
// Optional: Open the link in a new tab if needed
|
|
47
|
+
// const href = (e.currentTarget as HTMLAnchorElement).href;
|
|
48
|
+
// window.open(href, '_blank', 'noopener,noreferrer');
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
// Check if event is valid
|
|
52
|
+
if (!(event != null && event.date)) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const pullRequest = (_event$payload2 = event.payload) == null ? void 0 : _event$payload2.pull_request;
|
|
56
|
+
if (!pullRequest) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Extract repo, branches and user info
|
|
61
|
+
const repoFullName = event.repo;
|
|
62
|
+
const [repoOwner, repoName] = repoFullName.split('/');
|
|
63
|
+
const baseBranch = ((_pullRequest$base = pullRequest.base) == null ? void 0 : _pullRequest$base.ref) || 'unknown';
|
|
64
|
+
const headBranch = ((_pullRequest$head = pullRequest.head) == null ? void 0 : _pullRequest$head.ref) || 'unknown';
|
|
65
|
+
const authorLogin = ((_pullRequest$user = pullRequest.user) == null ? void 0 : _pullRequest$user.login) || event.user;
|
|
66
|
+
const authorAvatar = ((_pullRequest$user2 = pullRequest.user) == null ? void 0 : _pullRequest$user2.avatar_url) || event.avatarUrl;
|
|
67
|
+
|
|
68
|
+
// Check if PR is deleted or closed before making API call
|
|
69
|
+
const isPRDeleted = event.payload.action === 'deleted' || pullRequest.state === 'closed' || pullRequest.state === 'merged';
|
|
70
|
+
React.useEffect(() => {
|
|
71
|
+
// Skip if this is the same PR we've already loaded
|
|
72
|
+
if (requestIdRef.current === currentRequestId && prDetails !== null) {
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Track the current request
|
|
77
|
+
requestIdRef.current = currentRequestId;
|
|
78
|
+
let isMounted = true;
|
|
79
|
+
const fetchPRDetails = async () => {
|
|
80
|
+
try {
|
|
81
|
+
// If PR is deleted, don't make the API call
|
|
82
|
+
if (isPRDeleted) {
|
|
83
|
+
if (isMounted) {
|
|
84
|
+
setLoading(false);
|
|
85
|
+
setPrDetails({
|
|
86
|
+
title: pullRequest.title,
|
|
87
|
+
number: pullRequest.number,
|
|
88
|
+
state: pullRequest.state,
|
|
89
|
+
merged: pullRequest.merged,
|
|
90
|
+
user: pullRequest.user,
|
|
91
|
+
created_at: pullRequest.created_at,
|
|
92
|
+
updated_at: pullRequest.updated_at,
|
|
93
|
+
closed_at: pullRequest.closed_at,
|
|
94
|
+
merged_at: pullRequest.merged_at,
|
|
95
|
+
commits_list: [],
|
|
96
|
+
files: []
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (isMounted) {
|
|
102
|
+
setLoading(true);
|
|
103
|
+
setError(null);
|
|
104
|
+
}
|
|
105
|
+
try {
|
|
106
|
+
// Extract owner and repo from the repository URL
|
|
107
|
+
let owner, repo;
|
|
108
|
+
try {
|
|
109
|
+
const repoUrl = new URL(pullRequest.html_url);
|
|
110
|
+
const pathParts = repoUrl.pathname.split('/').filter(Boolean);
|
|
111
|
+
if (pathParts.length >= 2) {
|
|
112
|
+
owner = pathParts[0];
|
|
113
|
+
repo = pathParts[1];
|
|
114
|
+
} else {
|
|
115
|
+
throw new Error('Invalid repository URL');
|
|
116
|
+
}
|
|
117
|
+
} catch (urlError) {
|
|
118
|
+
// Fallback to the repo name if URL parsing fails
|
|
119
|
+
const [fallbackOwner, fallbackRepo] = repoFullName.split('/');
|
|
120
|
+
owner = fallbackOwner;
|
|
121
|
+
repo = fallbackRepo;
|
|
122
|
+
}
|
|
123
|
+
if (!owner || !repo || !pullRequest.number) {
|
|
124
|
+
throw new Error('Missing required information to fetch PR details');
|
|
125
|
+
}
|
|
126
|
+
const params = {
|
|
127
|
+
owner,
|
|
128
|
+
repo,
|
|
129
|
+
pull_number: pullRequest.number
|
|
130
|
+
};
|
|
131
|
+
const data = await getPRDetails({
|
|
132
|
+
apiUrl,
|
|
133
|
+
params
|
|
134
|
+
});
|
|
135
|
+
if (isMounted) {
|
|
136
|
+
setPrDetails(data);
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
console.error('Error fetching PR details:', err);
|
|
140
|
+
if (isMounted) {
|
|
141
|
+
setError(err instanceof Error ? err.message : 'Failed to load PR details');
|
|
142
|
+
}
|
|
143
|
+
} finally {
|
|
144
|
+
if (isMounted) {
|
|
145
|
+
setLoading(false);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
} catch (err) {
|
|
149
|
+
console.error('Error in PR details flow:', err);
|
|
150
|
+
if (isMounted) {
|
|
151
|
+
setLoading(false);
|
|
152
|
+
setError('An unexpected error occurred');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
fetchPRDetails();
|
|
157
|
+
|
|
158
|
+
// Cleanup function to prevent state updates if component unmounts
|
|
159
|
+
return () => {
|
|
160
|
+
isMounted = false;
|
|
161
|
+
};
|
|
162
|
+
}, [currentRequestId, isPRDeleted]); // Only depend on the request ID, not the entire object
|
|
163
|
+
|
|
164
|
+
const handleCheckout = hash => {
|
|
165
|
+
// TODO: Implement checkout functionality
|
|
166
|
+
};
|
|
167
|
+
|
|
168
|
+
// PR Header component with context info
|
|
169
|
+
const PrHeader = () => /*#__PURE__*/_jsxs(Box, {
|
|
170
|
+
sx: {
|
|
171
|
+
mb: 2
|
|
172
|
+
},
|
|
173
|
+
children: [/*#__PURE__*/_jsxs(Box, {
|
|
174
|
+
sx: {
|
|
175
|
+
display: 'flex',
|
|
176
|
+
alignItems: 'top',
|
|
177
|
+
justifyContent: 'space-between',
|
|
178
|
+
mb: 1
|
|
179
|
+
},
|
|
180
|
+
children: [/*#__PURE__*/_jsxs(Box, {
|
|
181
|
+
sx: {
|
|
182
|
+
display: 'flex',
|
|
183
|
+
alignItems: 'center',
|
|
184
|
+
gap: 1,
|
|
185
|
+
flexWrap: 'wrap'
|
|
186
|
+
},
|
|
187
|
+
children: [/*#__PURE__*/_jsx(Typography, {
|
|
188
|
+
variant: "caption",
|
|
189
|
+
color: "text.secondary",
|
|
190
|
+
children: event.date
|
|
191
|
+
}), /*#__PURE__*/_jsx(Chip, {
|
|
192
|
+
label: `${repoOwner}/${repoName}`,
|
|
193
|
+
size: "small",
|
|
194
|
+
color: "primary",
|
|
195
|
+
variant: "outlined"
|
|
196
|
+
}), /*#__PURE__*/_jsx(Chip, {
|
|
197
|
+
label: `#${pullRequest.number}`,
|
|
198
|
+
size: "small",
|
|
199
|
+
color: "default"
|
|
200
|
+
}), /*#__PURE__*/_jsx(Chip, {
|
|
201
|
+
label: pullRequest.state,
|
|
202
|
+
size: "small",
|
|
203
|
+
color: pullRequest.state === 'open' ? 'success' : 'error'
|
|
204
|
+
})]
|
|
205
|
+
}), /*#__PURE__*/_jsx(Button, {
|
|
206
|
+
sx: {
|
|
207
|
+
height: 'min-content',
|
|
208
|
+
padding: '8px',
|
|
209
|
+
'@media (min-width:40px)': {
|
|
210
|
+
display: 'none'
|
|
211
|
+
},
|
|
212
|
+
textTransform: 'none'
|
|
213
|
+
},
|
|
214
|
+
variant: "outlined",
|
|
215
|
+
size: "small",
|
|
216
|
+
startIcon: _CheckoutIcon || (_CheckoutIcon = /*#__PURE__*/_jsx(CheckoutIcon, {})),
|
|
217
|
+
onClick: e => {
|
|
218
|
+
e.preventDefault();
|
|
219
|
+
handleCheckout();
|
|
220
|
+
},
|
|
221
|
+
children: "Checkout"
|
|
222
|
+
})]
|
|
223
|
+
}), /*#__PURE__*/_jsx(Typography, {
|
|
224
|
+
variant: "h6",
|
|
225
|
+
component: "h3",
|
|
226
|
+
sx: {
|
|
227
|
+
mb: 1
|
|
228
|
+
},
|
|
229
|
+
children: /*#__PURE__*/_jsx(Link, {
|
|
230
|
+
href: pullRequest.html_url,
|
|
231
|
+
target: "_blank",
|
|
232
|
+
rel: "noopener noreferrer",
|
|
233
|
+
sx: {
|
|
234
|
+
textDecoration: 'none'
|
|
235
|
+
},
|
|
236
|
+
onClick: handleLinkClick,
|
|
237
|
+
children: pullRequest.title
|
|
238
|
+
})
|
|
239
|
+
}), /*#__PURE__*/_jsxs(Box, {
|
|
240
|
+
sx: {
|
|
241
|
+
display: 'flex',
|
|
242
|
+
alignItems: 'center',
|
|
243
|
+
gap: 1,
|
|
244
|
+
mb: 1
|
|
245
|
+
},
|
|
246
|
+
children: [/*#__PURE__*/_jsx(Avatar, {
|
|
247
|
+
src: authorAvatar,
|
|
248
|
+
alt: authorLogin,
|
|
249
|
+
sx: {
|
|
250
|
+
width: 24,
|
|
251
|
+
height: 24
|
|
252
|
+
}
|
|
253
|
+
}), _Typography || (_Typography = /*#__PURE__*/_jsx(Typography, {
|
|
254
|
+
variant: "body2",
|
|
255
|
+
children: authorLogin
|
|
256
|
+
})), _Typography2 || (_Typography2 = /*#__PURE__*/_jsx(Typography, {
|
|
257
|
+
variant: "body2",
|
|
258
|
+
color: "text.secondary",
|
|
259
|
+
children: "wants to merge from"
|
|
260
|
+
})), _Chip || (_Chip = /*#__PURE__*/_jsx(Chip, {
|
|
261
|
+
label: headBranch,
|
|
262
|
+
size: "small",
|
|
263
|
+
color: "default",
|
|
264
|
+
variant: "outlined"
|
|
265
|
+
})), _Typography3 || (_Typography3 = /*#__PURE__*/_jsx(Typography, {
|
|
266
|
+
variant: "body2",
|
|
267
|
+
color: "text.secondary",
|
|
268
|
+
children: "into"
|
|
269
|
+
})), _Chip2 || (_Chip2 = /*#__PURE__*/_jsx(Chip, {
|
|
270
|
+
label: baseBranch,
|
|
271
|
+
size: "small",
|
|
272
|
+
color: "default",
|
|
273
|
+
variant: "outlined"
|
|
274
|
+
}))]
|
|
275
|
+
})]
|
|
276
|
+
});
|
|
277
|
+
if (loading) {
|
|
278
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
279
|
+
sx: {
|
|
280
|
+
p: '16px'
|
|
281
|
+
},
|
|
282
|
+
children: [/*#__PURE__*/_jsx(PrHeader, {}), /*#__PURE__*/_jsx(Box, {
|
|
283
|
+
sx: {
|
|
284
|
+
display: 'flex',
|
|
285
|
+
justifyContent: 'center',
|
|
286
|
+
p: 4
|
|
287
|
+
},
|
|
288
|
+
children: _CircularProgress || (_CircularProgress = /*#__PURE__*/_jsx(CircularProgress, {}))
|
|
289
|
+
})]
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
if (error) {
|
|
293
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
294
|
+
sx: {
|
|
295
|
+
p: '16px'
|
|
296
|
+
},
|
|
297
|
+
children: [/*#__PURE__*/_jsx(PrHeader, {}), /*#__PURE__*/_jsx(Typography, {
|
|
298
|
+
color: "error",
|
|
299
|
+
children: error
|
|
300
|
+
}), isPRDeleted && /*#__PURE__*/_jsxs(Typography, {
|
|
301
|
+
color: "text.secondary",
|
|
302
|
+
sx: {
|
|
303
|
+
mt: 1
|
|
304
|
+
},
|
|
305
|
+
children: ["This pull request is no longer available.", pullRequest.state === 'merged' && ' It has been merged.', pullRequest.state === 'closed' && ' It has been closed.', event.payload.action === 'deleted' && ' It has been deleted.']
|
|
306
|
+
})]
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
if (!prDetails) {
|
|
310
|
+
return null;
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Transform the PR details into the format expected by PullRequestView
|
|
314
|
+
const transformedCommits = (prDetails.commits_list || []).map(commit => {
|
|
315
|
+
var _commit$author;
|
|
316
|
+
return {
|
|
317
|
+
id: commit.sha,
|
|
318
|
+
message: commit.commit.message,
|
|
319
|
+
author: {
|
|
320
|
+
name: commit.commit.author.name,
|
|
321
|
+
avatar: ((_commit$author = commit.author) == null ? void 0 : _commit$author.avatar_url) || ''
|
|
322
|
+
},
|
|
323
|
+
date: commit.commit.author.date,
|
|
324
|
+
hash: commit.sha
|
|
325
|
+
};
|
|
326
|
+
});
|
|
327
|
+
const transformedFiles = (prDetails.files || []).map(file => ({
|
|
328
|
+
path: file.path,
|
|
329
|
+
type: file.type,
|
|
330
|
+
additions: file.additions,
|
|
331
|
+
deletions: file.deletions,
|
|
332
|
+
diff: file.diff
|
|
333
|
+
}));
|
|
334
|
+
return /*#__PURE__*/_jsxs(Box, {
|
|
335
|
+
sx: {
|
|
336
|
+
p: '16px'
|
|
337
|
+
},
|
|
338
|
+
children: [/*#__PURE__*/_jsx(PrHeader, {}), /*#__PURE__*/_jsx(PullRequestView, {
|
|
339
|
+
title: "" // Set to empty to avoid duplicate title
|
|
340
|
+
,
|
|
341
|
+
number: prDetails.number,
|
|
342
|
+
commits: transformedCommits,
|
|
343
|
+
files: transformedFiles,
|
|
344
|
+
onCheckout: handleCheckout
|
|
345
|
+
})]
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Helper function to parse diff content into line objects
|
|
350
|
+
// function parseDiff(patch: string): Array<{ type: 'addition' | 'deletion' | 'context'; content: string; lineNumber: number }> {
|
|
351
|
+
// if (!patch) return [];
|
|
352
|
+
//
|
|
353
|
+
// return patch.split('\n').map((line, index) => {
|
|
354
|
+
// if (line.startsWith('+')) {
|
|
355
|
+
// return {
|
|
356
|
+
// type: 'addition',
|
|
357
|
+
// content: line,
|
|
358
|
+
// lineNumber: index + 1,
|
|
359
|
+
// };
|
|
360
|
+
// } else if (line.startsWith('-')) {
|
|
361
|
+
// return {
|
|
362
|
+
// type: 'deletion',
|
|
363
|
+
// content: line,
|
|
364
|
+
// lineNumber: index + 1,
|
|
365
|
+
// };
|
|
366
|
+
// } else {
|
|
367
|
+
// return {
|
|
368
|
+
// type: 'context',
|
|
369
|
+
// content: line,
|
|
370
|
+
// lineNumber: index + 1,
|
|
371
|
+
// };
|
|
372
|
+
// }
|
|
373
|
+
// });
|
|
374
|
+
// }
|