1- import React , { useState } from 'react' ;
2- import { Container , Paper , Modal , Box , Button , Typography , Tabs , Tab , Link as MuiLink , Tooltip , IconButton , Snackbar } from '@mui/material' ;
1+ import React , { useState , useEffect } from 'react' ;
2+ import { Container , Paper , Box , Button , Typography , Tabs , Tab , Link as MuiLink , Tooltip , IconButton , Snackbar , Grid , Accordion , AccordionSummary , AccordionDetails , Modal } from '@mui/material' ;
33import { ThemeProvider } from '@mui/material/styles' ;
44import DescriptionIcon from '@mui/icons-material/Description' ;
55import LibraryBooksIcon from '@mui/icons-material/LibraryBooks' ;
66import BlockIcon from '@mui/icons-material/Block' ;
77import ContentCopyIcon from '@mui/icons-material/ContentCopy' ;
88import DownloadIcon from '@mui/icons-material/Download' ;
9- import PreviewIcon from '@mui/icons-material/Visibility ' ;
9+ import ExpandMoreIcon from '@mui/icons-material/ExpandMore ' ;
1010import CloseIcon from '@mui/icons-material/Close' ;
11+ import GitHubIcon from '@mui/icons-material/GitHub' ;
1112import { BrowserRouter as Router , Routes , Route , Link , useLocation } from 'react-router-dom' ;
1213import theme from './theme' ;
1314import ContextForm from './components/ContextForm' ;
@@ -18,28 +19,78 @@ import './App.css';
1819// Conditional base path for GitHub Pages
1920const BASE_PATH = process . env . NODE_ENV === 'production' ? '/codebase-context-spec' : '' ;
2021
22+ const PromptViewer : React . FC < { title : string , content : string , onCopy : ( ) => void } > = ( { title, content, onCopy } ) => {
23+ return (
24+ < Box mb = { 2 } >
25+ < Box display = "flex" justifyContent = "space-between" alignItems = "center" mb = { 1 } >
26+ < Typography variant = "h6" > { title } </ Typography >
27+ < Button startIcon = { < ContentCopyIcon /> } onClick = { onCopy } >
28+ Copy
29+ </ Button >
30+ </ Box >
31+ < Box className = "code-preview" style = { { maxHeight : '300px' , overflow : 'auto' } } >
32+ < pre style = { { whiteSpace : 'pre-wrap' , wordBreak : 'break-word' } } >
33+ { content }
34+ </ pre >
35+ </ Box >
36+ </ Box >
37+ ) ;
38+ } ;
39+
40+ const SpecificationViewer : React . FC < { content : string , onCopy : ( ) => void } > = ( { content, onCopy } ) => {
41+ return (
42+ < Box height = "100%" display = "flex" flexDirection = "column" >
43+ < Box display = "flex" justifyContent = "flex-end" mb = { 2 } >
44+ < Button startIcon = { < ContentCopyIcon /> } onClick = { onCopy } >
45+ Copy Specification
46+ </ Button >
47+ </ Box >
48+ < Box flexGrow = { 1 } overflow = "auto" >
49+ < pre style = { { whiteSpace : 'pre-wrap' , wordBreak : 'break-word' , margin : 0 } } >
50+ { content }
51+ </ pre >
52+ </ Box >
53+ </ Box >
54+ ) ;
55+ } ;
56+
2157const App : React . FC = ( ) => {
22- const [ previewOpen , setPreviewOpen ] = useState ( false ) ;
2358 const [ generatedContent , setGeneratedContent ] = useState ( '' ) ;
2459 const [ snackbarOpen , setSnackbarOpen ] = useState ( false ) ;
2560 const [ snackbarMessage , setSnackbarMessage ] = useState ( '' ) ;
26- const [ promptModalOpen , setPromptModalOpen ] = useState ( false ) ;
27- const [ promptContent , setPromptContent ] = useState ( '' ) ;
61+ const [ codebaseContextContent , setCodebaseContextContent ] = useState ( '' ) ;
62+ const [ codingAssistantPromptContent , setCodingAssistantPromptContent ] = useState ( '' ) ;
63+ const [ generateContextPromptContent , setGenerateContextPromptContent ] = useState ( '' ) ;
64+ const [ specModalOpen , setSpecModalOpen ] = useState ( false ) ;
2865
29- const handleFormSubmit = ( content : string ) => {
30- setGeneratedContent ( content ) ;
31- } ;
66+ useEffect ( ( ) => {
67+ const fetchPrompts = async ( ) => {
68+ try {
69+ const [ codebaseContext , codingAssistantPrompt , generateContextPrompt ] = await Promise . all ( [
70+ fetch ( 'https://raw.githubusercontent.com/Agentic-Insights/codebase-context-spec/main/CODEBASE-CONTEXT.md' ) . then ( res => res . text ( ) ) ,
71+ fetch ( 'https://raw.githubusercontent.com/Agentic-Insights/codebase-context-spec/main/CODING-ASSISTANT-PROMPT.md' ) . then ( res => res . text ( ) ) ,
72+ fetch ( 'https://raw.githubusercontent.com/Agentic-Insights/codebase-context-spec/main/GENERATE-CONTEXT-PROMPT.md' ) . then ( res => res . text ( ) )
73+ ] ) ;
3274
33- const handleOpenPreview = ( ) => {
34- setPreviewOpen ( true ) ;
35- } ;
75+ setCodebaseContextContent ( codebaseContext ) ;
76+ setCodingAssistantPromptContent ( codingAssistantPrompt ) ;
77+ setGenerateContextPromptContent ( generateContextPrompt ) ;
78+ } catch ( error ) {
79+ console . error ( 'Error fetching prompts:' , error ) ;
80+ setSnackbarMessage ( 'Error fetching prompts' ) ;
81+ setSnackbarOpen ( true ) ;
82+ }
83+ } ;
84+
85+ fetchPrompts ( ) ;
86+ } , [ ] ) ;
3687
37- const handleClosePreview = ( ) => {
38- setPreviewOpen ( false ) ;
88+ const handleFormSubmit = ( content : string ) => {
89+ setGeneratedContent ( content ) ;
3990 } ;
4091
41- const handleCopyToClipboard = ( ) => {
42- navigator . clipboard . writeText ( generatedContent ) . then ( ( ) => {
92+ const handleCopyToClipboard = ( content : string ) => {
93+ navigator . clipboard . writeText ( content ) . then ( ( ) => {
4394 setSnackbarMessage ( 'Copied to clipboard!' ) ;
4495 setSnackbarOpen ( true ) ;
4596 } , ( err ) => {
@@ -66,49 +117,58 @@ const App: React.FC = () => {
66117 setSnackbarOpen ( false ) ;
67118 } ;
68119
69- const handleOpenPromptModal = async ( ) => {
70- try {
71- const response = await fetch ( 'https://raw.githubusercontent.com/Agentic-Insights/codebase-context-spec/main/GENERATE-CONTEXT-PROMPT.md' ) ;
72- const content = await response . text ( ) ;
73- setPromptContent ( content ) ;
74- setPromptModalOpen ( true ) ;
75- } catch ( error ) {
76- console . error ( 'Error fetching GENERATE-CONTEXT-PROMPT.md:' , error ) ;
77- setSnackbarMessage ( 'Error fetching prompt content' ) ;
78- setSnackbarOpen ( true ) ;
79- }
120+ const handleOpenSpecModal = ( ) => {
121+ setSpecModalOpen ( true ) ;
80122 } ;
81123
82- const handleClosePromptModal = ( ) => {
83- setPromptModalOpen ( false ) ;
124+ const handleCloseSpecModal = ( ) => {
125+ setSpecModalOpen ( false ) ;
84126 } ;
85127
86128 return (
87129 < ThemeProvider theme = { theme } >
88130 < Router basename = { BASE_PATH } >
89- < Container className = "container" maxWidth = "md " >
131+ < Container className = "container" maxWidth = "lg " >
90132 < Paper className = "paper" elevation = { 3 } >
91- < Box className = "header" >
133+ < Box className = "header" display = "flex" justifyContent = "space-between" alignItems = "center" >
92134 < Typography className = "title" variant = "h4" component = "h1" >
93135 Codebase Context Editor
94136 </ Typography >
137+ < Box display = "flex" alignItems = "center" >
138+ < Button variant = "outlined" onClick = { handleOpenSpecModal } sx = { { mr : 2 } } >
139+ View Latest Specification
140+ </ Button >
141+ < MuiLink href = "https://github.com/Agentic-Insights/codebase-context-spec" target = "_blank" rel = "noopener noreferrer" >
142+ < GitHubIcon fontSize = "large" />
143+ </ MuiLink >
144+ </ Box >
95145 </ Box >
96146 < Typography variant = "body1" paragraph >
97147 This editor helps you create .context.md, .contextdocs.md, and .contextignore files for your project.
98148 </ Typography >
99- < div className = "link-section" >
100- < Typography variant = "body1" paragraph >
101- GitHub Repository:{ ' ' }
102- < MuiLink href = "https://github.com/Agentic-Insights/codebase-context-spec" target = "_blank" rel = "noopener noreferrer" >
103- https://github.com/Agentic-Insights/codebase-context-spec
104- </ MuiLink >
105- </ Typography >
106- < Typography variant = "body1" paragraph >
107- < MuiLink href = "#" onClick = { handleOpenPromptModal } >
108- View GENERATE-CONTEXT-PROMPT
109- </ MuiLink >
110- </ Typography >
111- </ div >
149+ < Accordion >
150+ < AccordionSummary expandIcon = { < ExpandMoreIcon /> } >
151+ < Typography > View Prompts</ Typography >
152+ </ AccordionSummary >
153+ < AccordionDetails >
154+ < Grid container spacing = { 2 } >
155+ < Grid item xs = { 12 } md = { 6 } >
156+ < PromptViewer
157+ title = "CODING-ASSISTANT-PROMPT.md"
158+ content = { codingAssistantPromptContent }
159+ onCopy = { ( ) => handleCopyToClipboard ( codingAssistantPromptContent ) }
160+ />
161+ </ Grid >
162+ < Grid item xs = { 12 } md = { 6 } >
163+ < PromptViewer
164+ title = "GENERATE-CONTEXT-PROMPT.md"
165+ content = { generateContextPromptContent }
166+ onCopy = { ( ) => handleCopyToClipboard ( generateContextPromptContent ) }
167+ />
168+ </ Grid >
169+ </ Grid >
170+ </ AccordionDetails >
171+ </ Accordion >
112172 < NavTabs />
113173 < Box className = "form-section" >
114174 < Routes >
@@ -118,19 +178,9 @@ const App: React.FC = () => {
118178 </ Routes >
119179 </ Box >
120180 < Box className = "action-buttons" >
121- < Tooltip title = "Preview generated content" arrow >
122- < Button
123- onClick = { handleOpenPreview }
124- variant = "contained"
125- startIcon = { < PreviewIcon /> }
126- disabled = { ! generatedContent }
127- >
128- Preview
129- </ Button >
130- </ Tooltip >
131181 < Tooltip title = "Copy to clipboard" arrow >
132182 < Button
133- onClick = { handleCopyToClipboard }
183+ onClick = { ( ) => handleCopyToClipboard ( generatedContent ) }
134184 variant = "contained"
135185 startIcon = { < ContentCopyIcon /> }
136186 disabled = { ! generatedContent }
@@ -152,47 +202,38 @@ const App: React.FC = () => {
152202 </ Paper >
153203
154204 < Modal
155- open = { previewOpen }
156- onClose = { handleClosePreview }
157- aria-labelledby = "preview-modal-title"
158- aria-describedby = "preview-modal-description"
159- >
160- < Box className = "modal-content" >
161- < Box display = "flex" justifyContent = "space-between" alignItems = "center" mb = { 2 } >
162- < Typography id = "preview-modal-title" variant = "h6" component = "h2" >
163- Preview of generated content
164- </ Typography >
165- < IconButton onClick = { handleClosePreview } size = "small" >
166- < CloseIcon />
167- </ IconButton >
168- </ Box >
169- < Box className = "code-preview" >
170- < pre >
171- { generatedContent }
172- </ pre >
173- </ Box >
174- </ Box >
175- </ Modal >
176-
177- < Modal
178- open = { promptModalOpen }
179- onClose = { handleClosePromptModal }
180- aria-labelledby = "prompt-modal-title"
181- aria-describedby = "prompt-modal-description"
205+ open = { specModalOpen }
206+ onClose = { handleCloseSpecModal }
207+ aria-labelledby = "spec-modal-title"
182208 >
183- < Box className = "modal-content" >
209+ < Box
210+ sx = { {
211+ position : 'absolute' ,
212+ top : '50%' ,
213+ left : '50%' ,
214+ transform : 'translate(-50%, -50%)' ,
215+ width : '80%' ,
216+ height : '80%' ,
217+ bgcolor : 'background.paper' ,
218+ boxShadow : 24 ,
219+ p : 4 ,
220+ display : 'flex' ,
221+ flexDirection : 'column' ,
222+ } }
223+ >
184224 < Box display = "flex" justifyContent = "space-between" alignItems = "center" mb = { 2 } >
185- < Typography id = "prompt -modal-title" variant = "h6" component = "h2" >
186- GENERATE -CONTEXT-PROMPT
225+ < Typography id = "spec -modal-title" variant = "h6" component = "h2" >
226+ Latest Specification (CODEBASE -CONTEXT.md)
187227 </ Typography >
188- < IconButton onClick = { handleClosePromptModal } size = "small" >
228+ < IconButton onClick = { handleCloseSpecModal } size = "small" >
189229 < CloseIcon />
190230 </ IconButton >
191231 </ Box >
192- < Box className = "code-preview" >
193- < pre >
194- { promptContent }
195- </ pre >
232+ < Box flexGrow = { 1 } overflow = "hidden" >
233+ < SpecificationViewer
234+ content = { codebaseContextContent }
235+ onCopy = { ( ) => handleCopyToClipboard ( codebaseContextContent ) }
236+ />
196237 </ Box >
197238 </ Box >
198239 </ Modal >
0 commit comments