hale-commenting-system 2.0.2 → 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.
Files changed (58) hide show
  1. package/README.md +16 -207
  2. package/bin/detect.d.ts +1 -0
  3. package/bin/detect.js +62 -0
  4. package/bin/generators.d.ts +18 -0
  5. package/bin/generators.js +193 -0
  6. package/bin/hale-commenting.js +4 -0
  7. package/bin/index.d.ts +2 -0
  8. package/bin/index.js +61 -0
  9. package/bin/onboarding.d.ts +1 -0
  10. package/bin/onboarding.js +170 -0
  11. package/bin/postinstall.d.ts +2 -0
  12. package/bin/postinstall.js +65 -0
  13. package/bin/validators.d.ts +2 -0
  14. package/bin/validators.js +66 -0
  15. package/dist/cli/detect.d.ts +1 -0
  16. package/dist/cli/detect.js +62 -0
  17. package/dist/cli/generators.d.ts +18 -0
  18. package/dist/cli/generators.js +193 -0
  19. package/dist/cli/index.d.ts +2 -0
  20. package/dist/cli/index.js +61 -0
  21. package/dist/cli/onboarding.d.ts +1 -0
  22. package/dist/cli/onboarding.js +170 -0
  23. package/dist/cli/postinstall.d.ts +2 -0
  24. package/dist/cli/postinstall.js +65 -0
  25. package/dist/cli/validators.d.ts +2 -0
  26. package/dist/cli/validators.js +66 -0
  27. package/dist/components/CommentOverlay.d.ts +2 -0
  28. package/dist/components/CommentOverlay.js +101 -0
  29. package/dist/components/CommentPanel.d.ts +6 -0
  30. package/dist/components/CommentPanel.js +334 -0
  31. package/dist/components/CommentPin.d.ts +11 -0
  32. package/dist/components/CommentPin.js +64 -0
  33. package/dist/components/DetailsTab.d.ts +2 -0
  34. package/dist/components/DetailsTab.js +380 -0
  35. package/dist/components/FloatingWidget.d.ts +8 -0
  36. package/dist/components/FloatingWidget.js +128 -0
  37. package/dist/components/JiraTab.d.ts +2 -0
  38. package/dist/components/JiraTab.js +507 -0
  39. package/dist/contexts/CommentContext.d.ts +30 -0
  40. package/dist/contexts/CommentContext.js +891 -0
  41. package/dist/contexts/GitHubAuthContext.d.ts +13 -0
  42. package/dist/contexts/GitHubAuthContext.js +96 -0
  43. package/dist/index.d.ts +10 -97
  44. package/dist/index.js +26 -789
  45. package/dist/services/githubAdapter.d.ts +56 -0
  46. package/dist/services/githubAdapter.js +321 -0
  47. package/dist/types/index.d.ts +25 -0
  48. package/dist/types/index.js +2 -0
  49. package/dist/utils/version.d.ts +1 -0
  50. package/dist/utils/version.js +23 -0
  51. package/package.json +39 -38
  52. package/templates/webpack-middleware.js +226 -0
  53. package/cli/dist/index.js +0 -370
  54. package/cli/dist/index.js.map +0 -1
  55. package/dist/index.d.mts +0 -97
  56. package/dist/index.js.map +0 -1
  57. package/dist/index.mjs +0 -762
  58. package/dist/index.mjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/components/CommentOverlay.tsx","../src/contexts/CommentContext.tsx","../src/contexts/VersionContext.tsx","../src/components/CommentPin.tsx","../src/components/CommentDrawer.tsx","../src/contexts/GitLabAuthContext.tsx","../src/contexts/GitHubAuthContext.tsx"],"sourcesContent":["import * as React from 'react';\nimport { useLocation } from 'react-router-dom';\nimport { useComments } from '../contexts/CommentContext';\nimport { useVersion } from '../contexts/VersionContext';\nimport { CommentPin } from './CommentPin';\n\ninterface CommentOverlayProps {\n selectedThreadId: string | null;\n onThreadSelect: (id: string) => void;\n}\n\nexport const CommentOverlay: React.FunctionComponent<CommentOverlayProps> = ({\n selectedThreadId,\n onThreadSelect\n}) => {\n const location = useLocation();\n const { showPins, enableCommenting, addThread, getThreadsForRoute } = useComments();\n const { currentVersion } = useVersion();\n const overlayRef = React.useRef<HTMLDivElement>(null);\n\n const currentRouteThreads = React.useMemo(\n () => getThreadsForRoute(location.pathname, currentVersion),\n [getThreadsForRoute, location.pathname, currentVersion]\n );\n\n const handleOverlayClick = React.useCallback(\n (event: React.MouseEvent<HTMLDivElement>) => {\n if (!enableCommenting) return;\n\n // Only add thread if clicking the overlay itself, not a pin\n if (event.target === overlayRef.current) {\n const rect = overlayRef.current.getBoundingClientRect();\n const x = event.clientX - rect.left;\n const y = event.clientY - rect.top;\n const newThreadId = addThread(x, y, location.pathname, currentVersion);\n \n // Auto-open the drawer for the newly created thread\n onThreadSelect(newThreadId);\n }\n },\n [enableCommenting, addThread, location.pathname, currentVersion, onThreadSelect]\n );\n\n // Don't render anything if neither showPins nor enableCommenting are true\n if (!showPins && !enableCommenting) {\n return null;\n }\n\n return (\n <div\n ref={overlayRef}\n id=\"comment-overlay\"\n onClick={handleOverlayClick}\n style={{\n position: 'absolute',\n top: 0,\n left: 0,\n right: 0,\n bottom: 0,\n pointerEvents: enableCommenting ? 'auto' : 'none',\n cursor: enableCommenting ? 'crosshair' : 'default',\n zIndex: 999\n }}\n >\n {showPins && currentRouteThreads.map((thread) => (\n <div\n key={thread.id}\n style={{ pointerEvents: 'auto' }}\n onClick={(e) => e.stopPropagation()}\n >\n <CommentPin\n thread={thread}\n onPinClick={() => onThreadSelect(thread.id)}\n isSelected={thread.id === selectedThreadId}\n />\n </div>\n ))}\n </div>\n );\n};\n\n","import * as React from 'react';\n\nexport interface Comment {\n id: string;\n author?: string;\n text: string;\n createdAt: string;\n}\n\nexport interface Thread {\n id: string;\n x: number;\n y: number;\n route: string;\n comments: Comment[];\n version?: string;\n}\n\ninterface CommentContextType {\n threads: Thread[];\n showPins: boolean;\n enableCommenting: boolean;\n toggleShowPins: () => void;\n toggleEnableCommenting: () => void;\n addThread: (x: number, y: number, route: string, version?: string) => string;\n addReply: (threadId: string, text: string) => void;\n updateComment: (threadId: string, commentId: string, text: string) => void;\n deleteComment: (threadId: string, commentId: string) => void;\n deleteThread: (threadId: string) => void;\n clearAllThreads: () => void;\n getThreadsForRoute: (route: string, version?: string) => Thread[];\n}\n\nconst CommentContext = React.createContext<CommentContextType | undefined>(undefined);\n\nconst STORAGE_KEY = 'hale-threads';\nconst SHOW_PINS_KEY = 'hale-show-pins';\nconst ENABLE_COMMENTING_KEY = 'hale-enable-commenting';\n\n// Migration function to convert old Apollo comments to Hale threads\nconst migrateOldComments = (): Thread[] => {\n try {\n const oldThreadsKey = localStorage.getItem('apollo-threads');\n const oldCommentsKey = localStorage.getItem('apollo-comments');\n \n // Try apollo-threads first (newer format)\n if (oldThreadsKey) {\n const parsed = JSON.parse(oldThreadsKey);\n // Clean up sync-related fields\n const cleanThreads: Thread[] = parsed.map((t: any) => ({\n id: t.id,\n x: t.x,\n y: t.y,\n route: t.route,\n comments: t.comments.map((c: any) => ({\n id: c.id,\n text: c.text || '',\n createdAt: c.createdAt,\n author: c.author\n })),\n version: t.version\n }));\n localStorage.setItem(STORAGE_KEY, JSON.stringify(cleanThreads));\n localStorage.removeItem('apollo-threads');\n return cleanThreads;\n }\n \n // Fallback to old apollo-comments format (oldest)\n if (oldCommentsKey) {\n const parsed = JSON.parse(oldCommentsKey);\n const threads: Thread[] = parsed.map((oldComment: any) => ({\n id: oldComment.id,\n x: oldComment.x,\n y: oldComment.y,\n route: oldComment.route,\n comments: [\n {\n id: `${oldComment.id}-comment-0`,\n text: oldComment.text || '',\n createdAt: oldComment.createdAt\n }\n ]\n }));\n localStorage.setItem(STORAGE_KEY, JSON.stringify(threads));\n localStorage.removeItem('apollo-comments');\n return threads;\n }\n } catch (error) {\n console.error('Failed to migrate old comments:', error);\n }\n return [];\n};\n\nexport const CommentProvider: React.FunctionComponent<{ children: React.ReactNode }> = ({ children }) => {\n // Load initial state from localStorage with migration\n const [threads, setThreads] = React.useState<Thread[]>(() => {\n try {\n const stored = localStorage.getItem(STORAGE_KEY);\n if (stored) {\n return JSON.parse(stored);\n }\n // Try to migrate old comments\n return migrateOldComments();\n } catch (error) {\n console.error('Failed to load threads from localStorage:', error);\n return [];\n }\n });\n\n const [showPins, setShowPins] = React.useState<boolean>(() => {\n try {\n const stored = localStorage.getItem(SHOW_PINS_KEY);\n if (stored !== null) return stored === 'true';\n // Check old key for migration\n const oldKey = localStorage.getItem('apollo-show-pins');\n return oldKey === 'true';\n } catch (error) {\n return false;\n }\n });\n\n const [enableCommenting, setEnableCommenting] = React.useState<boolean>(() => {\n try {\n const stored = localStorage.getItem(ENABLE_COMMENTING_KEY);\n if (stored !== null) return stored === 'true';\n // Check old key for migration\n const oldKey = localStorage.getItem('apollo-enable-commenting');\n return oldKey === 'true';\n } catch (error) {\n return false;\n }\n });\n\n // Persist threads to localStorage whenever they change\n React.useEffect(() => {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(threads));\n } catch (error) {\n console.error('Failed to save threads to localStorage:', error);\n }\n }, [threads]);\n\n // Persist showPins to localStorage\n React.useEffect(() => {\n try {\n localStorage.setItem(SHOW_PINS_KEY, String(showPins));\n } catch (error) {\n console.error('Failed to save showPins to localStorage:', error);\n }\n }, [showPins]);\n\n // Persist enableCommenting to localStorage\n React.useEffect(() => {\n try {\n localStorage.setItem(ENABLE_COMMENTING_KEY, String(enableCommenting));\n } catch (error) {\n console.error('Failed to save enableCommenting to localStorage:', error);\n }\n }, [enableCommenting]);\n\n const toggleShowPins = React.useCallback(() => {\n setShowPins(prev => !prev);\n }, []);\n\n const toggleEnableCommenting = React.useCallback(() => {\n setEnableCommenting(prev => !prev);\n }, []);\n\n const addThread = React.useCallback((x: number, y: number, route: string, version?: string): string => {\n const threadId = `thread-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n const newThread: Thread = {\n id: threadId,\n x,\n y,\n route,\n comments: [],\n version\n };\n setThreads(prev => [...prev, newThread]);\n return threadId;\n }, []);\n\n const addReply = React.useCallback((threadId: string, text: string) => {\n const commentId = `${threadId}-comment-${Date.now()}`;\n const newComment: Comment = {\n id: commentId,\n text,\n createdAt: new Date().toISOString()\n };\n\n setThreads(prev =>\n prev.map(t => {\n if (t.id === threadId) {\n return {\n ...t,\n comments: [...t.comments, newComment]\n };\n }\n return t;\n })\n );\n }, []);\n\n const updateComment = React.useCallback((threadId: string, commentId: string, text: string) => {\n setThreads(prev =>\n prev.map(t => {\n if (t.id === threadId) {\n return {\n ...t,\n comments: t.comments.map(c =>\n c.id === commentId ? { ...c, text } : c\n )\n };\n }\n return t;\n })\n );\n }, []);\n\n const deleteComment = React.useCallback((threadId: string, commentId: string) => {\n setThreads(prev =>\n prev.map(t => {\n if (t.id === threadId) {\n return {\n ...t,\n comments: t.comments.filter(c => c.id !== commentId)\n };\n }\n return t;\n })\n );\n }, []);\n\n const deleteThread = React.useCallback((threadId: string) => {\n setThreads(prev => prev.filter(t => t.id !== threadId));\n }, []);\n\n const clearAllThreads = React.useCallback(() => {\n setThreads([]);\n }, []);\n\n const getThreadsForRoute = React.useCallback((route: string, version?: string): Thread[] => {\n return threads.filter(thread => {\n const routeMatch = thread.route === route;\n // Treat legacy comments (without version) as Version 3 (current)\n const threadVersion = thread.version || '3';\n const versionMatch = !version || threadVersion === version;\n return routeMatch && versionMatch;\n });\n }, [threads]);\n\n const value = React.useMemo(\n () => ({\n threads,\n showPins,\n enableCommenting,\n toggleShowPins,\n toggleEnableCommenting,\n addThread,\n addReply,\n updateComment,\n deleteComment,\n deleteThread,\n clearAllThreads,\n getThreadsForRoute\n }),\n [threads, showPins, enableCommenting, toggleShowPins, toggleEnableCommenting, addThread, addReply, updateComment, deleteComment, deleteThread, clearAllThreads, getThreadsForRoute]\n );\n\n return <CommentContext.Provider value={value}>{children}</CommentContext.Provider>;\n};\n\nexport const useComments = (): CommentContextType => {\n const context = React.useContext(CommentContext);\n if (!context) {\n throw new Error('useComments must be used within a CommentProvider');\n }\n return context;\n};\n","import * as React from 'react';\n\ninterface VersionContextType {\n currentVersion: string;\n setCurrentVersion: (version: string) => void;\n}\n\nconst VersionContext = React.createContext<VersionContextType | undefined>(undefined);\n\nconst VERSION_STORAGE_KEY = 'hale-current-version';\n\nexport const VersionProvider: React.FunctionComponent<{ children: React.ReactNode }> = ({ children }) => {\n const [currentVersion, setCurrentVersionState] = React.useState<string>(() => {\n try {\n const stored = localStorage.getItem(VERSION_STORAGE_KEY);\n return stored || '3'; // Default to version 3 (current)\n } catch (error) {\n console.error('Failed to load version from localStorage:', error);\n return '3';\n }\n });\n\n // Persist version to localStorage\n React.useEffect(() => {\n try {\n localStorage.setItem(VERSION_STORAGE_KEY, currentVersion);\n } catch (error) {\n console.error('Failed to save version to localStorage:', error);\n }\n }, [currentVersion]);\n\n const setCurrentVersion = React.useCallback((version: string) => {\n setCurrentVersionState(version);\n }, []);\n\n const value = React.useMemo(\n () => ({\n currentVersion,\n setCurrentVersion,\n }),\n [currentVersion, setCurrentVersion]\n );\n\n return <VersionContext.Provider value={value}>{children}</VersionContext.Provider>;\n};\n\nexport const useVersion = (): VersionContextType => {\n const context = React.useContext(VersionContext);\n if (!context) {\n throw new Error('useVersion must be used within a VersionProvider');\n }\n return context;\n};\n\n","import * as React from 'react';\nimport { Button } from '@patternfly/react-core';\nimport { CommentIcon, ExclamationTriangleIcon } from '@patternfly/react-icons';\nimport { Thread } from '../contexts/CommentContext';\n\ninterface CommentPinProps {\n thread: Thread;\n onPinClick: () => void;\n isSelected?: boolean;\n}\n\nexport const CommentPin: React.FunctionComponent<CommentPinProps> = ({ \n thread, \n onPinClick,\n isSelected = false\n}) => {\n const commentCount = thread.comments.length;\n // Sync status removed in local-only version\n\n return (\n <>\n <style>\n {`\n @keyframes pulse {\n 0%, 100% { opacity: 1; }\n 50% { opacity: 0.5; }\n }\n `}\n </style>\n <Button\n id={`comment-pin-${thread.id}`}\n variant=\"plain\"\n aria-label={`Comment thread with ${commentCount} ${commentCount === 1 ? 'comment' : 'comments'}`}\n onClick={(e) => {\n e.stopPropagation();\n onPinClick();\n }}\n style={{\n position: 'absolute',\n left: `${thread.x}px`,\n top: `${thread.y}px`,\n transform: 'translate(-50%, -50%)',\n width: '32px',\n height: '32px',\n borderRadius: '50%',\n backgroundColor: '#C9190B',\n color: 'white',\n border: isSelected ? '3px solid #0066CC' : '2px solid white',\n boxShadow: isSelected \n ? '0 0 0 2px #0066CC, 0 4px 12px rgba(0, 0, 0, 0.4)'\n : '0 2px 8px rgba(0, 0, 0, 0.3)',\n padding: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n cursor: 'pointer',\n zIndex: isSelected ? 1001 : 1000,\n transition: 'all 0.2s ease',\n fontSize: commentCount > 1 ? '0.7rem' : undefined\n }}\n >\n {commentCount === 0 ? (\n <span style={{ fontWeight: 'bold', fontSize: '0.75rem' }}>0</span>\n ) : commentCount === 1 ? (\n <CommentIcon />\n ) : (\n <span style={{ fontWeight: 'bold' }}>{commentCount}</span>\n )}\n </Button>\n </>\n );\n};\n\n","import * as React from 'react';\nimport {\n Drawer,\n DrawerContent,\n DrawerContentBody,\n DrawerPanelContent,\n DrawerHead,\n DrawerActions,\n DrawerCloseButton,\n Title,\n Button,\n TextArea,\n Card,\n CardBody,\n CardTitle,\n EmptyState,\n EmptyStateBody,\n Divider,\n Label,\n Spinner,\n ExpandableSection,\n Alert\n} from '@patternfly/react-core';\nimport { CommentIcon, TimesIcon, PlusCircleIcon, SyncAltIcon, GithubIcon, ExternalLinkAltIcon, RedoIcon, MagicIcon, InfoCircleIcon } from '@patternfly/react-icons';\nimport { useComments } from '../contexts/CommentContext';\nimport { useVersion } from '../contexts/VersionContext';\nimport { useLocation } from 'react-router-dom';\nimport { useGitLabAuth } from '../contexts/GitLabAuthContext';\n\ninterface CommentDrawerProps {\n children: React.ReactNode;\n selectedThreadId: string | null;\n onThreadSelect: (id: string | null) => void;\n}\n\nexport const CommentDrawer: React.FunctionComponent<CommentDrawerProps> = ({\n children,\n selectedThreadId,\n onThreadSelect\n}) => {\n const location = useLocation();\n const { \n getThreadsForRoute, \n addReply, \n updateComment, \n deleteComment,\n deleteThread,\n enableCommenting\n } = useComments();\n const { currentVersion } = useVersion();\n const { isAuthenticated: isGitLabAuthenticated } = useGitLabAuth();\n \n const [editingCommentId, setEditingCommentId] = React.useState<string | null>(null);\n const [editText, setEditText] = React.useState('');\n const [replyText, setReplyText] = React.useState('');\n const replyTextAreaRef = React.useRef<HTMLTextAreaElement>(null);\n \n // AI Summary state\n const [threadSummaries, setThreadSummaries] = React.useState<Record<string, string>>({});\n const [loadingSummary, setLoadingSummary] = React.useState(false);\n const [summaryExpanded, setSummaryExpanded] = React.useState(true);\n\n const currentRouteThreads = getThreadsForRoute(location.pathname, currentVersion);\n const selectedThread = currentRouteThreads.find(t => t.id === selectedThreadId);\n const isDrawerOpen = selectedThreadId !== null && selectedThread !== undefined;\n\n // Auto-focus reply textarea when drawer opens and commenting is enabled\n React.useEffect(() => {\n if (!isDrawerOpen || !enableCommenting) return;\n \n // Small delay to ensure drawer animation completes\n const timer = setTimeout(() => {\n replyTextAreaRef.current?.focus();\n }, 100);\n \n return () => clearTimeout(timer);\n }, [isDrawerOpen, enableCommenting, selectedThreadId]);\n\n // Note: Sync functionality removed in local-only version\n\n const handleEdit = (commentId: string, text: string) => {\n setEditingCommentId(commentId);\n setEditText(text);\n };\n\n const handleSave = async (threadId: string, commentId: string) => {\n await updateComment(threadId, commentId, editText);\n setEditingCommentId(null);\n };\n\n const handleAddReply = async () => {\n if (selectedThreadId && replyText.trim()) {\n await addReply(selectedThreadId, replyText);\n setReplyText('');\n }\n };\n\n const handleDeleteThread = async () => {\n if (selectedThreadId && window.confirm('Delete this entire thread and all its comments?')) {\n await deleteThread(selectedThreadId);\n onThreadSelect(null);\n }\n };\n\n const handleSummarizeThread = async () => {\n // AI summarization removed in local-only version\n console.log('AI features not available in local-only mode');\n };\n\n const handleDeleteComment = async (threadId: string, commentId: string) => {\n if (window.confirm('Delete this comment?')) {\n await deleteComment(threadId, commentId);\n }\n };\n\n // Sync handlers removed in local-only version\n\n const formatDate = (isoDate: string): string => {\n const date = new Date(isoDate);\n return date.toLocaleString(undefined, {\n month: 'short',\n day: 'numeric',\n hour: '2-digit',\n minute: '2-digit'\n });\n };\n\n const panelContent = (\n <DrawerPanelContent isResizable defaultSize=\"400px\" minSize=\"300px\">\n <DrawerHead>\n <div style={{ display: 'flex', alignItems: 'center', gap: '0.5rem', flex: 1 }}>\n <Title headingLevel=\"h2\" size=\"xl\">\n <CommentIcon style={{ marginRight: '0.5rem', color: '#C9190B' }} />\n Thread\n </Title>\n {/* Sync buttons removed in local-only version */}\n </div>\n <DrawerActions>\n <DrawerCloseButton onClick={() => onThreadSelect(null)} />\n </DrawerActions>\n </DrawerHead>\n <DrawerContentBody style={{ padding: '1rem' }}>\n {!selectedThread ? (\n <EmptyState>\n <CommentIcon style={{ fontSize: '3rem', color: 'var(--pf-v6-global--Color--200)', marginBottom: '1rem' }} />\n <Title headingLevel=\"h3\" size=\"lg\">\n No thread selected\n </Title>\n <EmptyStateBody>\n Click a pin to view its comments.\n </EmptyStateBody>\n </EmptyState>\n ) : (\n <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>\n {/* Thread Info */}\n <Card isCompact>\n <CardBody>\n <div style={{ fontSize: '0.875rem', marginBottom: '0.5rem' }}>\n <strong>Location:</strong> ({Math.round(selectedThread.x)}, {Math.round(selectedThread.y)})\n </div>\n {selectedThread.version && (\n <div style={{ fontSize: '0.875rem', marginBottom: '0.5rem' }}>\n <strong>Version:</strong> {selectedThread.version}\n </div>\n )}\n <div style={{ fontSize: '0.875rem', marginBottom: '0.5rem' }}>\n <strong>Comments:</strong> {selectedThread.comments.length}\n </div>\n {/* Status and issue link removed in local-only version */}\n {/* AI Summarize Thread Button */}\n {selectedThread.comments.length > 0 && (\n <Button\n id={`ai-summarize-thread-${selectedThread.id}`}\n variant=\"secondary\"\n size=\"sm\"\n icon={<MagicIcon />}\n onClick={handleSummarizeThread}\n isLoading={loadingSummary}\n isDisabled={loadingSummary}\n style={{ marginTop: '0.5rem' }}\n >\n {loadingSummary ? 'Generating...' : 'AI Summarize Thread'}\n </Button>\n )}\n {enableCommenting && (\n <Button\n id={`delete-thread-${selectedThread.id}`}\n variant=\"danger\"\n size=\"sm\"\n icon={<TimesIcon />}\n onClick={handleDeleteThread}\n style={{ marginTop: '0.5rem', marginLeft: selectedThread.comments.length > 0 ? '0.5rem' : '0' }}\n >\n Delete Thread\n </Button>\n )}\n </CardBody>\n </Card>\n\n {/* AI Summary Display */}\n {threadSummaries[selectedThread.id] && (\n <Alert\n variant=\"info\"\n isInline\n title=\"AI Summary\"\n actionClose={\n <Button\n variant=\"plain\"\n onClick={() => {\n const newSummaries = { ...threadSummaries };\n delete newSummaries[selectedThread.id];\n setThreadSummaries(newSummaries);\n }}\n aria-label=\"Clear summary\"\n >\n <TimesIcon />\n </Button>\n }\n >\n <ExpandableSection\n toggleText={summaryExpanded ? 'Hide summary' : 'Show summary'}\n onToggle={(_event, isExpanded) => setSummaryExpanded(isExpanded)}\n isExpanded={summaryExpanded}\n isIndented\n >\n <div style={{ fontSize: '0.875rem', lineHeight: '1.5' }}>\n {threadSummaries[selectedThread.id]}\n </div>\n </ExpandableSection>\n </Alert>\n )}\n\n <Divider />\n\n {/* Comments List */}\n <div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>\n {selectedThread.comments.length === 0 ? (\n <EmptyState>\n <Title headingLevel=\"h4\" size=\"md\">\n No comments yet\n </Title>\n <EmptyStateBody>\n {enableCommenting \n ? 'Add a reply below to start the conversation.'\n : 'Enable commenting to add replies.'}\n </EmptyStateBody>\n </EmptyState>\n ) : (\n selectedThread.comments.map((comment, index) => (\n <Card key={comment.id} isCompact>\n <CardTitle>\n Comment #{index + 1}\n <div style={{ fontSize: '0.75rem', color: 'var(--pf-v6-global--Color--200)', fontWeight: 'normal' }}>\n {comment.author && <span style={{ marginRight: '0.5rem' }}>@{comment.author}</span>}\n {formatDate(comment.createdAt)}\n </div>\n </CardTitle>\n <CardBody>\n {editingCommentId === comment.id ? (\n <>\n <TextArea\n id={`edit-comment-${comment.id}`}\n value={editText}\n onChange={(_event, value) => setEditText(value)}\n rows={3}\n style={{ marginBottom: '0.5rem' }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleSave(selectedThread.id, comment.id);\n }\n if (e.key === 'Escape') {\n setEditingCommentId(null);\n }\n }}\n />\n <div style={{ display: 'flex', gap: '0.5rem' }}>\n <Button\n id={`save-comment-${comment.id}`}\n variant=\"primary\"\n size=\"sm\"\n onClick={() => handleSave(selectedThread.id, comment.id)}\n >\n Save\n </Button>\n <Button\n id={`cancel-edit-${comment.id}`}\n variant=\"link\"\n size=\"sm\"\n onClick={() => setEditingCommentId(null)}\n >\n Cancel\n </Button>\n </div>\n </>\n ) : (\n <>\n <div style={{ marginBottom: '0.75rem', whiteSpace: 'pre-wrap' }}>\n {comment.text || <em style={{ color: 'var(--pf-v6-global--Color--200)' }}>No text</em>}\n </div>\n {enableCommenting && (\n <div style={{ display: 'flex', gap: '0.5rem' }}>\n <Button\n id={`edit-comment-btn-${comment.id}`}\n variant=\"secondary\"\n size=\"sm\"\n onClick={() => handleEdit(comment.id, comment.text)}\n >\n Edit\n </Button>\n <Button\n id={`delete-comment-btn-${comment.id}`}\n variant=\"danger\"\n size=\"sm\"\n icon={<TimesIcon />}\n onClick={() => handleDeleteComment(selectedThread.id, comment.id)}\n >\n Delete\n </Button>\n </div>\n )}\n </>\n )}\n </CardBody>\n </Card>\n ))\n )}\n </div>\n\n {/* Add Reply */}\n {enableCommenting && (\n <>\n <Divider />\n <Card isCompact>\n <CardTitle>\n <PlusCircleIcon style={{ marginRight: '0.5rem' }} />\n Add Reply\n </CardTitle>\n <CardBody>\n <TextArea\n ref={replyTextAreaRef}\n id={`reply-textarea-${selectedThread.id}`}\n value={replyText}\n onChange={(_event, value) => setReplyText(value)}\n placeholder=\"Enter your reply...\"\n rows={3}\n style={{ marginBottom: '0.5rem' }}\n onKeyDown={(e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n handleAddReply();\n }\n }}\n />\n <Button\n id={`add-reply-${selectedThread.id}`}\n variant=\"primary\"\n size=\"sm\"\n onClick={handleAddReply}\n isDisabled={!replyText.trim()}\n >\n Add Reply\n </Button>\n </CardBody>\n </Card>\n </>\n )}\n </div>\n )}\n </DrawerContentBody>\n </DrawerPanelContent>\n );\n\n return (\n <Drawer isExpanded={isDrawerOpen} isInline position=\"right\">\n <DrawerContent panelContent={panelContent}>\n <DrawerContentBody>{children}</DrawerContentBody>\n </DrawerContent>\n </Drawer>\n );\n};\n","import * as React from 'react';\n\ninterface GitLabUser {\n username?: string;\n avatar?: string;\n}\n\ninterface GitLabAuthContextType {\n user: GitLabUser | null;\n isAuthenticated: boolean;\n login: () => void;\n logout: () => void;\n getToken: () => string | null;\n}\n\nconst GitLabAuthContext = React.createContext<GitLabAuthContextType | undefined>(undefined);\n\n// Mock provider for local-only mode (no actual OAuth)\nexport const GitLabAuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {\n const value = {\n user: null,\n isAuthenticated: false,\n login: () => {\n console.log('GitLab login not available in local mode');\n },\n logout: () => {\n console.log('GitLab logout not available in local mode');\n },\n getToken: () => null,\n };\n\n return (\n <GitLabAuthContext.Provider value={value}>\n {children}\n </GitLabAuthContext.Provider>\n );\n};\n\nexport const useGitLabAuth = () => {\n const ctx = React.useContext(GitLabAuthContext);\n if (!ctx) {\n throw new Error('useGitLabAuth must be used within a GitLabAuthProvider');\n }\n return ctx;\n};\n","import * as React from 'react';\n\ninterface GitHubUser {\n login: string;\n avatar: string;\n}\n\ninterface GitHubAuthContextType {\n user: GitHubUser | null;\n isAuthenticated: boolean;\n login: () => void;\n logout: () => void;\n}\n\nconst GitHubAuthContext = React.createContext<GitHubAuthContextType | undefined>(undefined);\n\n// Mock provider for local-only mode (no actual OAuth)\nexport const GitHubAuthProvider: React.FC<{ children: React.ReactNode; config?: any }> = ({ children }) => {\n const value = {\n user: null,\n isAuthenticated: false,\n login: () => {\n console.log('GitHub login not available in local mode');\n },\n logout: () => {\n console.log('GitHub logout not available in local mode');\n },\n };\n\n return (\n <GitHubAuthContext.Provider value={value}>\n {children}\n </GitHubAuthContext.Provider>\n );\n};\n\nexport const useGitHubAuth = () => {\n const context = React.useContext(GitHubAuthContext);\n if (context === undefined) {\n throw new Error('useGitHubAuth must be used within a GitHubAuthProvider');\n }\n return context;\n};\n"],"mappings":"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","names":["React","React","jsx","jsx","jsx","React","Button","CommentIcon","useLocation","React","jsx","Fragment","jsx","jsxs","useLocation","CommentIcon","Button","React","jsx"]}