hale-commenting-system 2.0.3 → 2.0.4
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/README.md +16 -207
- package/bin/detect.d.ts +1 -0
- package/bin/detect.js +62 -0
- package/bin/generators.d.ts +18 -0
- package/bin/generators.js +193 -0
- package/bin/hale-commenting.js +4 -0
- package/bin/index.d.ts +2 -0
- package/bin/index.js +61 -0
- package/bin/onboarding.d.ts +1 -0
- package/bin/onboarding.js +170 -0
- package/bin/postinstall.d.ts +2 -0
- package/bin/postinstall.js +65 -0
- package/bin/validators.d.ts +2 -0
- package/bin/validators.js +66 -0
- package/dist/cli/detect.d.ts +1 -0
- package/dist/cli/detect.js +62 -0
- package/dist/cli/generators.d.ts +18 -0
- package/dist/cli/generators.js +193 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +61 -0
- package/dist/cli/onboarding.d.ts +1 -0
- package/dist/cli/onboarding.js +170 -0
- package/dist/cli/postinstall.d.ts +2 -0
- package/dist/cli/postinstall.js +65 -0
- package/dist/cli/validators.d.ts +2 -0
- package/dist/cli/validators.js +66 -0
- package/dist/components/CommentOverlay.d.ts +2 -0
- package/dist/components/CommentOverlay.js +101 -0
- package/dist/components/CommentPanel.d.ts +6 -0
- package/dist/components/CommentPanel.js +334 -0
- package/dist/components/CommentPin.d.ts +11 -0
- package/dist/components/CommentPin.js +64 -0
- package/dist/components/DetailsTab.d.ts +2 -0
- package/dist/components/DetailsTab.js +380 -0
- package/dist/components/FloatingWidget.d.ts +8 -0
- package/dist/components/FloatingWidget.js +128 -0
- package/dist/components/JiraTab.d.ts +2 -0
- package/dist/components/JiraTab.js +507 -0
- package/dist/contexts/CommentContext.d.ts +30 -0
- package/dist/contexts/CommentContext.js +891 -0
- package/dist/contexts/GitHubAuthContext.d.ts +13 -0
- package/dist/contexts/GitHubAuthContext.js +96 -0
- package/dist/index.d.ts +10 -97
- package/dist/index.js +26 -786
- package/dist/services/githubAdapter.d.ts +56 -0
- package/dist/services/githubAdapter.js +321 -0
- package/dist/types/index.d.ts +25 -0
- package/dist/types/index.js +2 -0
- package/dist/utils/version.d.ts +1 -0
- package/dist/utils/version.js +23 -0
- package/package.json +39 -38
- package/templates/webpack-middleware.js +226 -0
- package/cli/dist/index.js +0 -370
- package/cli/dist/index.js.map +0 -1
- package/dist/index.d.mts +0 -97
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -759
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CommentPanel = void 0;
|
|
37
|
+
const React = __importStar(require("react"));
|
|
38
|
+
const react_router_dom_1 = require("react-router-dom");
|
|
39
|
+
const react_core_1 = require("@patternfly/react-core");
|
|
40
|
+
const react_icons_1 = require("@patternfly/react-icons");
|
|
41
|
+
const CommentContext_1 = require("../contexts/CommentContext");
|
|
42
|
+
const DetailsTab_1 = require("./DetailsTab");
|
|
43
|
+
const JiraTab_1 = require("./JiraTab");
|
|
44
|
+
const FloatingWidget_1 = require("./FloatingWidget");
|
|
45
|
+
const version_1 = require("../utils/version");
|
|
46
|
+
const CommentPanel = ({ children }) => {
|
|
47
|
+
const { getThreadsForRoute, selectedThreadId, setSelectedThreadId, drawerPinnedOpen, setDrawerPinnedOpen, floatingWidgetMode, setFloatingWidgetMode, addReply, updateComment, deleteComment, closeThread, reopenThread, removePin, retrySync, } = (0, CommentContext_1.useComments)();
|
|
48
|
+
const location = (0, react_router_dom_1.useLocation)();
|
|
49
|
+
const detectedVersion = (0, version_1.getVersionFromPathOrQuery)(location.pathname, location.search);
|
|
50
|
+
const [newCommentText, setNewCommentText] = React.useState('');
|
|
51
|
+
const [replyingToCommentId, setReplyingToCommentId] = React.useState(null);
|
|
52
|
+
const [replyTextByCommentId, setReplyTextByCommentId] = React.useState({});
|
|
53
|
+
const [editingCommentId, setEditingCommentId] = React.useState(null);
|
|
54
|
+
const [editText, setEditText] = React.useState('');
|
|
55
|
+
const drawerRef = React.useRef(null);
|
|
56
|
+
const [activeTabKey, setActiveTabKey] = React.useState('comments');
|
|
57
|
+
const currentThreads = getThreadsForRoute(location.pathname, detectedVersion);
|
|
58
|
+
const selectedThread = currentThreads.find((t) => t.id === selectedThreadId);
|
|
59
|
+
const isExpanded = !!selectedThreadId || drawerPinnedOpen || floatingWidgetMode;
|
|
60
|
+
const onExpand = () => {
|
|
61
|
+
drawerRef.current && drawerRef.current.focus();
|
|
62
|
+
};
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
if (selectedThreadId) {
|
|
65
|
+
setActiveTabKey('comments');
|
|
66
|
+
}
|
|
67
|
+
}, [selectedThreadId]);
|
|
68
|
+
React.useEffect(() => {
|
|
69
|
+
if (drawerPinnedOpen && !selectedThreadId) {
|
|
70
|
+
setActiveTabKey('details');
|
|
71
|
+
}
|
|
72
|
+
}, [drawerPinnedOpen, selectedThreadId]);
|
|
73
|
+
const handleAddComment = () => {
|
|
74
|
+
if (newCommentText.trim() && selectedThread) {
|
|
75
|
+
addReply(selectedThread.id, newCommentText.trim());
|
|
76
|
+
setNewCommentText('');
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const handleStartReply = (commentId) => {
|
|
80
|
+
setReplyingToCommentId(commentId);
|
|
81
|
+
setReplyTextByCommentId((prev) => ({ ...prev, [commentId]: prev[commentId] ?? '' }));
|
|
82
|
+
};
|
|
83
|
+
const handleCancelReply = () => {
|
|
84
|
+
setReplyingToCommentId(null);
|
|
85
|
+
};
|
|
86
|
+
const handleSubmitReply = (parentCommentId) => {
|
|
87
|
+
if (!selectedThread)
|
|
88
|
+
return;
|
|
89
|
+
const text = (replyTextByCommentId[parentCommentId] || '').trim();
|
|
90
|
+
if (!text)
|
|
91
|
+
return;
|
|
92
|
+
addReply(selectedThread.id, text, parentCommentId);
|
|
93
|
+
setReplyTextByCommentId((prev) => ({ ...prev, [parentCommentId]: '' }));
|
|
94
|
+
setReplyingToCommentId(null);
|
|
95
|
+
};
|
|
96
|
+
const handleStartEdit = (commentId, currentText) => {
|
|
97
|
+
setEditingCommentId(commentId);
|
|
98
|
+
setEditText(currentText);
|
|
99
|
+
};
|
|
100
|
+
const handleSaveEdit = (commentId) => {
|
|
101
|
+
if (editText.trim() && selectedThread) {
|
|
102
|
+
updateComment(selectedThread.id, commentId, editText.trim());
|
|
103
|
+
setEditingCommentId(null);
|
|
104
|
+
setEditText('');
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
const handleCancelEdit = () => {
|
|
108
|
+
setEditingCommentId(null);
|
|
109
|
+
setEditText('');
|
|
110
|
+
};
|
|
111
|
+
const handleDeleteComment = (commentId) => {
|
|
112
|
+
if (selectedThread) {
|
|
113
|
+
deleteComment(selectedThread.id, commentId);
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
const handleCloseThread = () => {
|
|
117
|
+
if (selectedThread) {
|
|
118
|
+
closeThread(selectedThread.id);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const handleReopenThread = () => {
|
|
122
|
+
if (selectedThread) {
|
|
123
|
+
reopenThread(selectedThread.id);
|
|
124
|
+
}
|
|
125
|
+
};
|
|
126
|
+
const handleRemovePin = () => {
|
|
127
|
+
if (!selectedThread)
|
|
128
|
+
return;
|
|
129
|
+
removePin(selectedThread.id);
|
|
130
|
+
};
|
|
131
|
+
const handleClose = () => {
|
|
132
|
+
setSelectedThreadId(null);
|
|
133
|
+
if (floatingWidgetMode) {
|
|
134
|
+
setFloatingWidgetMode(false);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
setDrawerPinnedOpen(false);
|
|
138
|
+
}
|
|
139
|
+
setEditingCommentId(null);
|
|
140
|
+
setEditText('');
|
|
141
|
+
setNewCommentText('');
|
|
142
|
+
setReplyingToCommentId(null);
|
|
143
|
+
setReplyTextByCommentId({});
|
|
144
|
+
};
|
|
145
|
+
const formatCommentDate = (isoDate) => {
|
|
146
|
+
const date = new Date(isoDate);
|
|
147
|
+
return date.toLocaleString(undefined, {
|
|
148
|
+
month: 'short',
|
|
149
|
+
day: 'numeric',
|
|
150
|
+
hour: '2-digit',
|
|
151
|
+
minute: '2-digit',
|
|
152
|
+
});
|
|
153
|
+
};
|
|
154
|
+
const stripMarkersForDisplay = (text) => {
|
|
155
|
+
return text
|
|
156
|
+
.replace(/<!--\s*hale-reply-to:\d+\s*-->\s*\n?/g, '')
|
|
157
|
+
.replace(/<!--\s*hale-reply-to-local\s*-->\s*\n?/g, '')
|
|
158
|
+
.trimEnd();
|
|
159
|
+
};
|
|
160
|
+
const deriveStatus = () => {
|
|
161
|
+
if (!selectedThread)
|
|
162
|
+
return 'local';
|
|
163
|
+
if (selectedThread.syncStatus === 'error')
|
|
164
|
+
return 'error';
|
|
165
|
+
// If we have an issue and any comment hasn't synced yet, treat as pending.
|
|
166
|
+
if (selectedThread.issueNumber && selectedThread.comments.some((c) => !c.githubCommentId))
|
|
167
|
+
return 'pending';
|
|
168
|
+
if (selectedThread.issueNumber)
|
|
169
|
+
return 'synced';
|
|
170
|
+
return selectedThread.syncStatus || 'local';
|
|
171
|
+
};
|
|
172
|
+
const renderSyncLabel = (status) => {
|
|
173
|
+
switch (status) {
|
|
174
|
+
case 'synced':
|
|
175
|
+
return (React.createElement(react_core_1.Label, { color: "green", icon: React.createElement(react_icons_1.GithubIcon, null) }, "Synced"));
|
|
176
|
+
case 'local':
|
|
177
|
+
return React.createElement(react_core_1.Label, { color: "grey" }, "Local");
|
|
178
|
+
case 'pending':
|
|
179
|
+
return React.createElement(react_core_1.Label, { color: "blue" }, "Pending\u2026");
|
|
180
|
+
case 'syncing':
|
|
181
|
+
return (React.createElement(react_core_1.Label, { color: "blue", icon: React.createElement(react_core_1.Spinner, { size: "sm" }) }, "Syncing\u2026"));
|
|
182
|
+
case 'error':
|
|
183
|
+
return React.createElement(react_core_1.Label, { color: "red" }, "Sync error");
|
|
184
|
+
default:
|
|
185
|
+
return null;
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
const panelContent = (React.createElement(React.Fragment, null,
|
|
189
|
+
React.createElement(react_core_1.Tabs, { activeKey: activeTabKey, onSelect: (_event, tabKey) => setActiveTabKey(tabKey), "aria-label": "Hale Commenting System drawer tabs" },
|
|
190
|
+
React.createElement(react_core_1.Tab, { eventKey: "details", title: React.createElement(react_core_1.TabTitleText, null, "Details") },
|
|
191
|
+
React.createElement("div", { style: { paddingTop: '1rem' } },
|
|
192
|
+
React.createElement(DetailsTab_1.DetailsTab, null))),
|
|
193
|
+
React.createElement(react_core_1.Tab, { eventKey: "jira", title: React.createElement(react_core_1.TabTitleText, null, "Jira") },
|
|
194
|
+
React.createElement("div", { style: { paddingTop: '1rem' } },
|
|
195
|
+
React.createElement(JiraTab_1.JiraTab, null))),
|
|
196
|
+
React.createElement(react_core_1.Tab, { eventKey: "comments", title: React.createElement(react_core_1.TabTitleText, null, "Comments") },
|
|
197
|
+
React.createElement("div", { style: { paddingTop: '1rem' } }, !selectedThread ? (React.createElement(react_core_1.EmptyState, { icon: react_icons_1.InfoCircleIcon, titleText: "No pin selected", headingLevel: "h3" },
|
|
198
|
+
React.createElement(react_core_1.EmptyStateBody, null, "Select or create a comment pin to start a thread."))) : (React.createElement(React.Fragment, null,
|
|
199
|
+
React.createElement(react_core_1.Card, { style: { marginBottom: '1rem' } },
|
|
200
|
+
React.createElement(react_core_1.CardBody, null,
|
|
201
|
+
React.createElement("div", { style: { display: 'grid', gap: '0.5rem' } },
|
|
202
|
+
React.createElement("div", { style: { fontSize: '0.875rem' } },
|
|
203
|
+
React.createElement("strong", null, "Location:"),
|
|
204
|
+
" (",
|
|
205
|
+
selectedThread.xPercent.toFixed(1),
|
|
206
|
+
"%, ",
|
|
207
|
+
selectedThread.yPercent.toFixed(1),
|
|
208
|
+
"%)"),
|
|
209
|
+
React.createElement("div", { style: { fontSize: '0.875rem' } },
|
|
210
|
+
React.createElement("strong", null, "Comments:"),
|
|
211
|
+
" ",
|
|
212
|
+
selectedThread.comments.length),
|
|
213
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '0.5rem', fontSize: '0.875rem' } },
|
|
214
|
+
React.createElement("strong", null, "Status:"),
|
|
215
|
+
renderSyncLabel(deriveStatus()) ?? React.createElement(react_core_1.Label, { color: "grey" }, "Local")),
|
|
216
|
+
React.createElement("div", { style: { fontSize: '0.875rem' } }, selectedThread.issueNumber && selectedThread.issueUrl ? (React.createElement("a", { href: selectedThread.issueUrl, target: "_blank", rel: "noopener noreferrer", style: { display: 'inline-flex', alignItems: 'center', gap: '0.25rem' } },
|
|
217
|
+
React.createElement(react_icons_1.GithubIcon, null),
|
|
218
|
+
"Issue #",
|
|
219
|
+
selectedThread.issueNumber,
|
|
220
|
+
React.createElement(react_icons_1.ExternalLinkAltIcon, { style: { fontSize: '0.75rem' } }))) : (React.createElement("span", { style: { display: 'inline-flex', alignItems: 'center', gap: '0.25rem', color: 'var(--pf-t--global--text--color--subtle)' } },
|
|
221
|
+
React.createElement(react_icons_1.GithubIcon, null),
|
|
222
|
+
"Issue pending\u2026"))),
|
|
223
|
+
React.createElement("div", null)))),
|
|
224
|
+
selectedThread.comments.length > 0 && (React.createElement("div", { style: { marginBottom: '1.5rem' } }, (() => {
|
|
225
|
+
const comments = selectedThread.comments;
|
|
226
|
+
const byId = new Map(comments.map((c) => [c.id, c]));
|
|
227
|
+
const byGitHubId = new Map();
|
|
228
|
+
for (const c of comments) {
|
|
229
|
+
if (c.githubCommentId)
|
|
230
|
+
byGitHubId.set(c.githubCommentId, c.id);
|
|
231
|
+
}
|
|
232
|
+
const childrenByParent = new Map();
|
|
233
|
+
const topLevel = [];
|
|
234
|
+
for (const c of comments) {
|
|
235
|
+
const parentLocal = c.parentCommentId ||
|
|
236
|
+
(c.parentGitHubCommentId ? byGitHubId.get(c.parentGitHubCommentId) : undefined);
|
|
237
|
+
if (parentLocal && byId.has(parentLocal)) {
|
|
238
|
+
const list = childrenByParent.get(parentLocal) || [];
|
|
239
|
+
list.push(c.id);
|
|
240
|
+
childrenByParent.set(parentLocal, list);
|
|
241
|
+
}
|
|
242
|
+
else {
|
|
243
|
+
topLevel.push(c.id);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
const sortByCreatedAt = (aId, bId) => {
|
|
247
|
+
const a = byId.get(aId);
|
|
248
|
+
const b = byId.get(bId);
|
|
249
|
+
const at = a ? Date.parse(a.createdAt) : 0;
|
|
250
|
+
const bt = b ? Date.parse(b.createdAt) : 0;
|
|
251
|
+
return at - bt;
|
|
252
|
+
};
|
|
253
|
+
topLevel.sort(sortByCreatedAt);
|
|
254
|
+
childrenByParent.forEach((list, parentId) => {
|
|
255
|
+
list.sort(sortByCreatedAt);
|
|
256
|
+
childrenByParent.set(parentId, list);
|
|
257
|
+
});
|
|
258
|
+
const renderNode = (id, depth, topIndex) => {
|
|
259
|
+
const comment = byId.get(id);
|
|
260
|
+
if (!comment)
|
|
261
|
+
return null;
|
|
262
|
+
const isReply = depth > 0;
|
|
263
|
+
const title = isReply ? 'Reply' : `Comment #${(topIndex ?? 0) + 1}`;
|
|
264
|
+
const children = childrenByParent.get(id) || [];
|
|
265
|
+
return (React.createElement("div", { key: id, style: {
|
|
266
|
+
marginLeft: depth * 16,
|
|
267
|
+
marginTop: depth > 0 ? '8px' : undefined,
|
|
268
|
+
marginBottom: depth > 0 ? '8px' : '1rem',
|
|
269
|
+
} },
|
|
270
|
+
React.createElement(react_core_1.Card, null,
|
|
271
|
+
React.createElement(react_core_1.CardBody, { style: { position: 'relative' } },
|
|
272
|
+
React.createElement(react_core_1.Button, { variant: "plain", icon: React.createElement(react_icons_1.TrashIcon, null), isDanger: true, "aria-label": "Delete comment", title: "Delete comment", onClick: () => handleDeleteComment(comment.id), style: { position: 'absolute', top: '12px', right: '12px' } }),
|
|
273
|
+
React.createElement(react_core_1.Title, { headingLevel: "h3", size: isReply ? 'lg' : 'xl', style: { paddingRight: '2.5rem' } }, title),
|
|
274
|
+
React.createElement("div", { style: {
|
|
275
|
+
marginTop: '0.25rem',
|
|
276
|
+
fontSize: '0.875rem',
|
|
277
|
+
color: 'var(--pf-t--global--text--color--subtle)',
|
|
278
|
+
paddingRight: '2.5rem',
|
|
279
|
+
} },
|
|
280
|
+
"@",
|
|
281
|
+
comment.author ?? '—',
|
|
282
|
+
" \u00A0 ",
|
|
283
|
+
formatCommentDate(comment.createdAt)),
|
|
284
|
+
editingCommentId === comment.id ? (React.createElement("div", { style: { marginTop: '0.5rem' } },
|
|
285
|
+
React.createElement(react_core_1.TextArea, { value: editText, onChange: (_event, value) => setEditText(value), "aria-label": "Edit comment", rows: 3 }),
|
|
286
|
+
React.createElement(react_core_1.ActionList, { style: { marginTop: '0.5rem' } },
|
|
287
|
+
React.createElement(react_core_1.ActionListItem, null,
|
|
288
|
+
React.createElement(react_core_1.Button, { variant: "primary", onClick: () => handleSaveEdit(comment.id) }, "Save")),
|
|
289
|
+
React.createElement(react_core_1.ActionListItem, null,
|
|
290
|
+
React.createElement(react_core_1.Button, { variant: "link", onClick: handleCancelEdit }, "Cancel"))))) : (React.createElement("div", null,
|
|
291
|
+
React.createElement("div", { style: { marginTop: '0.75rem', whiteSpace: 'pre-wrap' } }, stripMarkersForDisplay(comment.text)),
|
|
292
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', marginTop: '0.5rem' } },
|
|
293
|
+
React.createElement(react_core_1.Button, { variant: "primary", onClick: () => handleStartReply(comment.id) }, "Reply"),
|
|
294
|
+
React.createElement(react_core_1.Button, { variant: "link", onClick: () => handleStartEdit(comment.id, stripMarkersForDisplay(comment.text)) }, "Edit")))),
|
|
295
|
+
replyingToCommentId === comment.id && (React.createElement("div", { style: { marginTop: '0.75rem' } },
|
|
296
|
+
React.createElement(react_core_1.Title, { headingLevel: "h4", size: "md", style: { marginBottom: '0.5rem' } }, "Reply to this comment"),
|
|
297
|
+
React.createElement(react_core_1.TextArea, { value: replyTextByCommentId[comment.id] || '', onChange: (_event, value) => setReplyTextByCommentId((prev) => ({ ...prev, [comment.id]: value })), placeholder: "Type your reply...", "aria-label": "Reply to comment", rows: 3 }),
|
|
298
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', marginTop: '0.5rem' } },
|
|
299
|
+
React.createElement(react_core_1.Button, { variant: "primary", onClick: () => handleSubmitReply(comment.id), isDisabled: !(replyTextByCommentId[comment.id] || '').trim() }, "Post reply"),
|
|
300
|
+
React.createElement(react_core_1.Button, { variant: "link", onClick: handleCancelReply }, "Cancel")))))),
|
|
301
|
+
children.map((childId) => renderNode(childId, depth + 1))));
|
|
302
|
+
};
|
|
303
|
+
return React.createElement(React.Fragment, null, topLevel.map((id, idx) => renderNode(id, 0, idx)));
|
|
304
|
+
})())),
|
|
305
|
+
React.createElement("div", null, selectedThread.status === 'closed' ? (React.createElement("div", { style: { marginBottom: '1rem', padding: '1rem', backgroundColor: 'var(--pf-t--global--background--color--secondary--default)', borderRadius: 'var(--pf-t--global--border--radius--medium)' } },
|
|
306
|
+
React.createElement(react_core_1.Title, { headingLevel: "h3", size: "md", style: { marginBottom: '0.5rem' } }, "\uD83D\uDD12 Thread Closed"),
|
|
307
|
+
React.createElement("p", { style: { color: 'var(--pf-t--global--text--color--subtle)', marginBottom: '1rem' } }, "This thread has been closed and locked. Reopen it to add new comments."),
|
|
308
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', flexWrap: 'wrap' } },
|
|
309
|
+
React.createElement(react_core_1.Button, { variant: "primary", onClick: handleReopenThread }, "Reopen Thread"),
|
|
310
|
+
React.createElement(react_core_1.Button, { variant: "link", isDanger: true, onClick: handleRemovePin }, "Remove pin")))) : (React.createElement(React.Fragment, null,
|
|
311
|
+
React.createElement(react_core_1.Title, { headingLevel: "h3", size: "md", style: { marginBottom: '0.5rem' } }, "Add comment"),
|
|
312
|
+
React.createElement(react_core_1.TextArea, { value: newCommentText, onChange: (_event, value) => setNewCommentText(value), placeholder: "Type your comment...", "aria-label": "New comment", rows: 4 }),
|
|
313
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', marginTop: '1rem' } },
|
|
314
|
+
React.createElement(react_core_1.Button, { variant: "primary", onClick: handleAddComment, isDisabled: !newCommentText.trim() }, "Add Comment"),
|
|
315
|
+
React.createElement(react_core_1.Button, { variant: "secondary", onClick: handleCloseThread }, "Close Thread"),
|
|
316
|
+
React.createElement(react_core_1.Button, { variant: "link", isDanger: true, onClick: handleRemovePin }, "Remove pin"))))))))))));
|
|
317
|
+
if (floatingWidgetMode && isExpanded) {
|
|
318
|
+
return (React.createElement(React.Fragment, null,
|
|
319
|
+
React.createElement(FloatingWidget_1.FloatingWidget, { onClose: handleClose, title: "Hale Commenting System" },
|
|
320
|
+
React.createElement("div", { style: { padding: '1rem' } }, panelContent)),
|
|
321
|
+
React.createElement("div", { style: { position: 'relative' } }, children)));
|
|
322
|
+
}
|
|
323
|
+
const drawerPanelContent = isExpanded ? (React.createElement(react_core_1.DrawerPanelContent, { isResizable: true, defaultSize: '500px', minSize: '300px' },
|
|
324
|
+
React.createElement(react_core_1.DrawerHead, null,
|
|
325
|
+
React.createElement("span", { tabIndex: isExpanded ? 0 : -1, ref: drawerRef },
|
|
326
|
+
React.createElement(react_core_1.Title, { headingLevel: "h2", size: "lg" }, "Hale Commenting System")),
|
|
327
|
+
React.createElement(react_core_1.DrawerActions, null,
|
|
328
|
+
React.createElement(react_core_1.DrawerCloseButton, { onClick: handleClose }))),
|
|
329
|
+
React.createElement(react_core_1.DrawerPanelBody, null, panelContent))) : null;
|
|
330
|
+
return (React.createElement(react_core_1.Drawer, { isExpanded: isExpanded, isInline: true, onExpand: onExpand },
|
|
331
|
+
React.createElement(react_core_1.DrawerContent, { panelContent: drawerPanelContent },
|
|
332
|
+
React.createElement(react_core_1.DrawerContentBody, { style: { position: 'relative' } }, children))));
|
|
333
|
+
};
|
|
334
|
+
exports.CommentPanel = CommentPanel;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
interface CommentPinProps {
|
|
3
|
+
xPercent: number;
|
|
4
|
+
yPercent: number;
|
|
5
|
+
commentCount: number;
|
|
6
|
+
isClosed?: boolean;
|
|
7
|
+
isSelected: boolean;
|
|
8
|
+
onClick: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const CommentPin: React.FunctionComponent<CommentPinProps>;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.CommentPin = void 0;
|
|
37
|
+
const React = __importStar(require("react"));
|
|
38
|
+
const react_core_1 = require("@patternfly/react-core");
|
|
39
|
+
const react_icons_1 = require("@patternfly/react-icons");
|
|
40
|
+
const CommentPin = ({ xPercent, yPercent, commentCount, isClosed = false, isSelected, onClick, }) => {
|
|
41
|
+
return (React.createElement(react_core_1.Button, { variant: "plain", "data-comment-pin": true, style: {
|
|
42
|
+
position: 'absolute',
|
|
43
|
+
left: `${xPercent}%`,
|
|
44
|
+
top: `${yPercent}%`,
|
|
45
|
+
transform: 'translate(-50%, -50%)',
|
|
46
|
+
width: '32px',
|
|
47
|
+
height: '32px',
|
|
48
|
+
borderRadius: '50%',
|
|
49
|
+
backgroundColor: isClosed ? 'var(--pf-t--global--icon--color--subtle)' : '#C9190B',
|
|
50
|
+
color: 'white',
|
|
51
|
+
border: isSelected ? '3px solid #0066CC' : '2px solid white',
|
|
52
|
+
boxShadow: isSelected
|
|
53
|
+
? '0 0 0 3px rgba(0, 102, 204, 0.3), 0 2px 8px rgba(0,0,0,0.3)'
|
|
54
|
+
: '0 2px 8px rgba(0,0,0,0.3)',
|
|
55
|
+
cursor: 'pointer',
|
|
56
|
+
padding: 0,
|
|
57
|
+
display: 'flex',
|
|
58
|
+
alignItems: 'center',
|
|
59
|
+
justifyContent: 'center',
|
|
60
|
+
transition: 'all 0.2s ease',
|
|
61
|
+
pointerEvents: 'auto',
|
|
62
|
+
}, onClick: onClick, "aria-label": `${isClosed ? 'Closed ' : ''}comment thread with ${commentCount} comment${commentCount !== 1 ? 's' : ''}` }, commentCount === 0 ? (React.createElement(react_icons_1.CommentIcon, { style: { fontSize: '16px' } })) : commentCount === 1 ? (React.createElement(react_icons_1.CommentIcon, { style: { fontSize: '16px' } })) : (React.createElement("span", { style: { fontSize: '14px', fontWeight: 'bold' } }, commentCount))));
|
|
63
|
+
};
|
|
64
|
+
exports.CommentPin = CommentPin;
|