Dashboard  2
Lot's of data
Loading...
Searching...
No Matches
github_widget.ts
Go to the documentation of this file.
1/*
2** EPITECH PROJECT, 2024
3** area-rattrapage
4** File description:
5** github_widget.ts
6*/
7
8export namespace GithubWidget {
9 export function injectGlobalCSS(widgetId: string): void {
10 const css = `
11 #${widgetId} {
12 border: 2px solid #333;
13 background: #f9f9f9;
14 padding: 10px;
15 margin: 10px auto;
16 border-radius: 5px;
17 width: 400px;
18 height: 600px;
19 display: flex;
20 flex-direction: column;
21 overflow: hidden;
22 box-sizing: border-box;
23 }
24
25 #${widgetId} h3, #${widgetId} h4 {
26 color: #0366d6;
27 margin-bottom: 5px;
28 }
29
30 #${widgetId} ul {
31 list-style: none;
32 padding: 0;
33 margin: 0;
34 }
35
36 #${widgetId} li {
37 padding: 5px 0;
38 }
39
40 #${widgetId} a {
41 text-decoration: none;
42 color: #0366d6;
43 font-weight: bold;
44 }
45
46 #${widgetId} a:hover {
47 text-decoration: underline;
48 }
49
50 #${widgetId} .repositories {
51 height: 50%;
52 display: flex;
53 flex-direction: column;
54 overflow: hidden;
55 position: relative;
56 }
57
58 #${widgetId} .repositories_list {
59 background: #E8FFCEFF;
60 min-height: 0;
61 display: flex;
62 flex-direction: column;
63 gap: 5px;
64 overflow-y: auto;
65 scrollbar-width: thin;
66 scrollbar-color: #0366d6 #f9f9f9;
67 height: 60px;
68 }
69
70 #${widgetId} .repositories_list::-webkit-scrollbar {
71 width: 8px;
72 }
73
74 #${widgetId} .repositories_list::-webkit-scrollbar-thumb {
75 background: #0366d6;
76 border-radius: 4px;
77 }
78
79 #${widgetId} .repositories_list::-webkit-scrollbar-track {
80 background: #f9f9f9;
81 }
82 `;
83
84 const styleElement = document.createElement("style");
85 styleElement.innerHTML = css;
86 document.head.appendChild(styleElement);
87 }
88
89 export function stringFunctionInjectGlobalCSS(widgetId: string): string {
90 return `
91 <script type="text/javascript">
92 const css = \`
93 #${widgetId} {border: 2px solid #333;background: #f9f9f9;padding: 10px;margin: 10px auto;border-radius: 5px;width: 400px;height: 600px;display: flex;flex-direction: column;overflow: hidden;box-sizing: border-box;}
94 #${widgetId} h3, #${widgetId} h4 {color: #0366d6;margin-bottom: 5px;}
95 #${widgetId} ul {list-style: none;padding: 0;margin: 0;}
96 #${widgetId} li {padding: 5px 0;}
97 #${widgetId} a {text-decoration: none;color: #0366d6;font-weight: bold;}
98 #${widgetId} a:hover {text-decoration: underline;}
99 #${widgetId} .repositories {height: 50%;display: flex;flex-direction: column;overflow: hidden;position: relative;}
100 #${widgetId} .repositories_list {background: #E8FFCEFF;min-height: 0;display: flex;flex-direction: column;gap: 5px;overflow-y: auto;scrollbar-width: thin;scrollbar-color: #0366d6 #f9f9f9;height: 60px;}
101 #${widgetId} .repositories_list::-webkit-scrollbar {width: 8px;}
102 #${widgetId} .repositories_list::-webkit-scrollbar-thumb {background: #0366d6;border-radius: 4px;}
103 #${widgetId} .repositories_list::-webkit-scrollbar-track {background: #f9f9f9;}
104 \`;
105 const styleElement = document.createElement("style");styleElement.innerHTML = css;document.head.appendChild(styleElement);
106 </script>
107 `;
108 }
109
110 export function sortRepositories(repositories: any[]): any[] {
111 return repositories.sort((a, b) => (a.private === b.private ? 0 : a.private ? -1 : 1));
112 }
113
114 export async function fetchAllRepositories(token: string, maxPages = 100): Promise<any[]> {
115 if (!token) {
116 console.error("No access token provided.");
117 return [];
118 }
119
120 let allRepos: any[] = [];
121 let page = 1;
122 const perPage = 100;
123 let hasMore = true;
124
125 while (hasMore && page <= maxPages) {
126 console.log("Page", page);
127 console.log("hasMore", hasMore);
128 console.log("Token: ", token);
129 try {
130 const response = await fetch(`https://api.github.com/user/repos?per_page=${perPage}&page=${page}`, {
131 headers: { Authorization: `Bearer ${token}` }
132 });
133
134 // console.log("Response", response);
135
136 if (!response.ok) throw new Error(`GitHub API error: ${response.status}`);
137
138 console.log("Attempting to jsonize response");
139
140 const repos = await response.json();
141 // console.log("Response jsonized", repos);
142 allRepos = [...allRepos, ...repos];
143 // console.log("All repos", allRepos);
144 hasMore = repos.length === perPage;
145 page++;
146 } catch (error) {
147 console.error("Error fetching repositories:", error);
148 return [];
149 }
150 }
151 return allRepos;
152 }
153
154 export async function fetchOrganizations(token: string): Promise<any[]> {
155 if (!token) {
156 console.error("No access token provided.");
157 return [];
158 }
159
160 try {
161 const response = await fetch("https://api.github.com/user/orgs", {
162 headers: { Authorization: `Bearer ${token}` }
163 });
164
165 if (!response.ok) throw new Error(`GitHub API error: ${response.status}`);
166
167 return await response.json();
168 } catch (error) {
169 console.error("Error fetching organizations:", error);
170 return [];
171 }
172 }
173
174 export async function renderGithubWidget(
175 widgetId: string,
176 listType: string,
177 allRepos: any[],
178 organizations: any[]
179 ): Promise<string> {
180 let html = `<div id="${widgetId}" class="github_widget_body">`;
181 html += `<h3>Organizations (${organizations.length})</h3>`;
182 html += organizations.length ? `<ul>` : `<p><strong>No organizations found.</strong></p>`;
183 organizations.forEach(org => {
184 html += `<li><a href="${org.html_url}" target="_blank">${org.login}</a></li>`;
185 });
186 html += organizations.length ? `</ul>` : "";
187
188 html += `<h3>Repositories (${allRepos.length})</h3>`;
189 let privateRepos = "<ul class='private_repos'>";
190 let publicRepos = "<ul class='public_repos'>";
191 let privateReposCount = 0;
192 let publicReposCount = 0;
193
194 allRepos.forEach(repo => {
195 const fork = repo.fork ? "<span class='repo_fork'>Forked</span>" : "<span class='repo_not_fork'>Not Forked</span>";
196 const tags = repo.topics?.length ? repo.topics.join(", ") : "No tags";
197 const description = repo.description ? `<p class='repo_description'>${repo.description}</p>` : "";
198
199 const repoHTML = `
200 <li>
201 <a href="${repo.html_url}" target="_blank">${repo.name}</a>
202 ${fork} | Tags: ${tags} ${description}
203 </li>
204 `;
205
206 if (repo.private) {
207 privateRepos += repoHTML;
208 privateReposCount++;
209 } else {
210 publicRepos += repoHTML;
211 publicReposCount++;
212 }
213 });
214
215 privateRepos += "</ul>";
216 publicRepos += "</ul>";
217
218 html += `<h4>Private Repositories (${privateReposCount})</h4>${privateRepos}`;
219 html += `<h4>Public Repositories (${publicReposCount})</h4>${publicRepos}`;
220 html += `</div>`;
221 return html;
222 }
223
224 export async function injector(widget_name: string, index: number, token: string): Promise<string> {
225 const widgetId = `${widget_name}_${index}`;
226 const listType = "numbered";
227
228 console.log("injector: token", token);
229
230 console.log("Fetching repositories...");
231 const allRepos = await fetchAllRepositories(token);
232 console.log("Fetching organizations...");
233 const organizations = await fetchOrganizations(token);
234 console.log("Rendering widget...");
235 return await renderGithubWidget(widgetId, listType, allRepos, organizations);
236 }
237};