1+ document . addEventListener ( "DOMContentLoaded" , function ( ) {
2+ setupFormHandler ( ) ;
3+ setupNotificationSystem ( ) ;
4+ } ) ;
5+
6+ // This works by creating an object with methods for different notification types of either error or success
7+ // Calling either of these methods calls the main functionality, show(), which manipulates the notification element in HTML
8+ // The show() method changes the element based on type and displays the message to the user
9+ // The hide() function makes sure that the notification fades away after 5 seconds
10+ const notificationSystem = {
11+ show : function ( message , type = 'error' ) {
12+ const notification = document . getElementById ( 'notification' ) ;
13+ const messageElement = document . getElementById ( 'notification-message' ) ;
14+
15+ messageElement . textContent = message ;
16+
17+ if ( type === 'error' ) {
18+ notification . style . backgroundColor = '#f8d7da' ;
19+ notification . style . color = '#721c24' ;
20+ notification . style . border = '1px solid #f5c6cb' ;
21+ } else {
22+ notification . style . backgroundColor = '#d4edda' ;
23+ notification . style . color = '#155724' ;
24+ notification . style . border = '1px solid #c3e6cb' ;
25+ }
26+
27+ notification . style . display = 'block' ;
28+ setTimeout ( ( ) => {
29+ notification . style . opacity = '1' ;
30+ } , 10 ) ;
31+
32+ clearTimeout ( this . timeout ) ;
33+ this . timeout = setTimeout ( ( ) => this . hide ( ) , 5000 ) ;
34+ } ,
35+
36+ hide : function ( ) {
37+ const notification = document . getElementById ( 'notification' ) ;
38+ notification . style . opacity = '0' ;
39+ setTimeout ( ( ) => {
40+ notification . style . display = 'none' ;
41+ } , 500 ) ;
42+ } ,
43+
44+ error : function ( message ) {
45+ this . show ( message , 'error' ) ;
46+ } ,
47+
48+ success : function ( message ) {
49+ this . show ( message , 'success' ) ;
50+ } ,
51+ } ;
52+
53+ function setupNotificationSystem ( ) {
54+ const notification = document . getElementById ( 'notification' ) ;
55+ if ( notification ) {
56+ notification . style . opacity = '0' ;
57+ notification . style . transition = 'opacity 0.5s ease' ;
58+ }
59+ }
60+
61+ function setupFormHandler ( ) {
62+ const form = document . getElementById ( "github-url-form" ) ;
63+
64+ form . addEventListener ( "submit" , async function ( event ) {
65+ event . preventDefault ( ) ;
66+
67+ const submitButton = document . getElementById ( "repo-url-button" ) ;
68+
69+ submitButton . value = "Loading..." ;
70+ submitButton . disabled = true ;
71+
72+ try {
73+ const repoURL = document . getElementById ( "repo-url" ) . value ;
74+
75+ if ( repoURL . length == 0 ) {
76+ throw new Error ( "Please enter a GitHub repository URL" ) ;
77+ }
78+
79+ const repoInfo = extractGitHubInfo ( repoURL ) ;
80+
81+ if ( ! repoInfo ) {
82+ throw new Error ( "Invalid GitHub URL format. Please enter a valid GitHub repository URL ->(https://github.com/username/repository)" ) ;
83+ }
84+
85+ const repositoryInfo = await getRepoInformation ( repoInfo ) ;
86+ const languages = await getRepoLanguages ( repoInfo )
87+
88+ if ( repositoryInfo ) {
89+ preFillFields ( repositoryInfo , languages ) ;
90+ notificationSystem . success ( "Repository data loaded successfully!" ) ;
91+ } else {
92+ throw new Error ( "Could not fetch repository information. Please check the URL and try again." ) ;
93+ }
94+
95+ } catch ( error ) {
96+ console . error ( error . message ) ;
97+ notificationSystem . error ( error . message ) ;
98+ } finally {
99+ submitButton . value = "Submit" ;
100+ submitButton . disabled = false ;
101+ }
102+ } ) ;
103+ }
104+
105+ function extractGitHubInfo ( url ) {
106+ // Regex pattern to match GitHub URLs and extract org and repo
107+ const regex = / (?: h t t p s ? : \/ \/ ) ? (?: w w w \. ) ? g i t h u b \. c o m \/ ( [ ^ \/ ] + ) \/ ( [ ^ \/ \s ] + ) / ;
108+ const match = url . match ( regex ) ;
109+
110+ if ( match && match . length === 3 ) {
111+ return {
112+ organization : match [ 1 ] ,
113+ repository : match [ 2 ]
114+ } ;
115+ }
116+
117+ return null ;
118+ }
119+
120+ async function getRepoInformation ( repoInfo ) {
121+ const baseURL = "https://api.github.com/repos/" ;
122+ const endpoint = `${ baseURL } ${ repoInfo . organization } /${ repoInfo . repository } ` ;
123+
124+ try {
125+ const response = await fetch ( endpoint ) ;
126+
127+ if ( ! response . ok ) {
128+ throw new Error ( `GitHub API error (${ response . status } ): ${ response . statusText } ` ) ;
129+ }
130+
131+ return await response . json ( ) ;
132+ } catch ( error ) {
133+ console . error ( "Fetch error:" , error . message ) ;
134+ }
135+ }
136+
137+ async function getRepoLanguages ( repoInfo ) {
138+ const endpoint = `https://api.github.com/repos/${ repoInfo . organization } /${ repoInfo . repository } /languages`
139+
140+ try {
141+ const response = await fetch ( endpoint ) ;
142+
143+ if ( ! response . ok ) {
144+ throw new Error ( `GitHub API error (${ response . status } ): ${ response . statusText } ` ) ;
145+ }
146+
147+ return await response . json ( ) ;
148+ } catch ( error ) {
149+ console . error ( "Fetch error:" , error . message ) ;
150+ }
151+ }
152+
153+ function preFillFields ( repoData , languages ) {
154+ if ( ! window . formIOInstance ) {
155+ notificationSystem . error ( "Form interface not initialized. Please refresh and try again." ) ;
156+ return ;
157+ }
158+
159+ try {
160+ const currentSubmission = { }
161+
162+ window . formIOInstance . components . forEach ( component => {
163+ if ( component . components ) {
164+ component . components . forEach ( nestedComp => {
165+ if ( nestedComp . key ) {
166+ currentSubmission [ nestedComp . key ] = nestedComp . getValue ( )
167+ }
168+ } ) ;
169+ } else if ( component . key ) {
170+ currentSubmission [ component . key ] = component . getValue ( )
171+ }
172+ } )
173+
174+ let licenses = [ ] ;
175+ if ( repoData . license && repoData . license . spdx_id ) {
176+ licenses . push ( {
177+ name : repoData . license . spdx_id ,
178+ URL : repoData . html_url + "/blob/main/LICENSE"
179+ } ) ;
180+ }
181+
182+ const newSubmission = {
183+ name : repoData . name || '' ,
184+ description : repoData . description || '' ,
185+ repositoryURL : repoData . html_url || '' ,
186+ repositoryVisibility : repoData . private ? "private" : "public" ,
187+ vcs : 'git' ,
188+ permissions : {
189+ licenses : licenses
190+ } ,
191+ reuseFrequency : {
192+ forks : repoData . forks_count || 0
193+ } ,
194+ languages : Object . keys ( languages ) || [ ] ,
195+ date : {
196+ created : repoData . created_at || '' ,
197+ lastModified : repoData . updated_at || '' ,
198+ metaDataLastUpdated : new Date ( ) . toISOString ( )
199+ } ,
200+ tags : repoData . topics || [ ] ,
201+ feedbackMechanisms : [ repoData . html_url + "/issues" ]
202+ }
203+
204+ const mergedSubmission = { ...currentSubmission , ...newSubmission }
205+
206+ window . formIOInstance . setSubmission ( { data : mergedSubmission } )
207+
208+ } catch ( error ) {
209+ notificationSystem . error ( "Error filling form fields with repository data. Please refresh and try again" ) ;
210+ console . error ( "Form fill error:" , error ) ;
211+ }
212+ }
213+
214+ // This is global so we could use this throughout the website!
215+ window . showErrorNotification = function ( message ) {
216+ notificationSystem . error ( message ) ;
217+ } ;
218+
219+ window . showSuccessNotification = function ( message ) {
220+ notificationSystem . success ( message ) ;
221+ } ;
0 commit comments