2** EPITECH PROJECT, 2024
8export namespace GithubWidget {
9 export function injectGlobalCSS(widgetId: string): void {
12 border: 2px solid #333;
20 flex-direction: column;
22 box-sizing: border-box;
25 #${widgetId} h3, #${widgetId} h4 {
41 text-decoration: none;
46 #${widgetId} a:hover {
47 text-decoration: underline;
50 #${widgetId} .repositories {
53 flex-direction: column;
58 #${widgetId} .repositories_list {
59 background: #E8FFCEFF;
62 flex-direction: column;
65 scrollbar-width: thin;
66 scrollbar-color: #0366d6 #f9f9f9;
70 #${widgetId} .repositories_list::-webkit-scrollbar {
74 #${widgetId} .repositories_list::-webkit-scrollbar-thumb {
79 #${widgetId} .repositories_list::-webkit-scrollbar-track {
84 const styleElement = document.createElement("style");
85 styleElement.innerHTML = css;
86 document.head.appendChild(styleElement);
89 export function stringFunctionInjectGlobalCSS(widgetId: string): string {
91 <script type="text/javascript">
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;}
105 const styleElement = document.createElement("style");styleElement.innerHTML = css;document.head.appendChild(styleElement);
110 export function sortRepositories(repositories: any[]): any[] {
111 return repositories.sort((a, b) => (a.private === b.private ? 0 : a.private ? -1 : 1));
114 export async function fetchAllRepositories(token: string, maxPages = 100): Promise<any[]> {
116 console.error("No access token provided.");
120 let allRepos: any[] = [];
125 while (hasMore && page <= maxPages) {
126 console.log("Page", page);
127 console.log("hasMore", hasMore);
128 console.log("Token: ", token);
130 const response = await fetch(`https://api.github.com/user/repos?per_page=${perPage}&page=${page}`, {
131 headers: { Authorization: `Bearer ${token}` }
134 // console.log("Response", response);
136 if (!response.ok) throw new Error(`GitHub API error: ${response.status}`);
138 console.log("Attempting to jsonize response");
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;
147 console.error("Error fetching repositories:", error);
154 export async function fetchOrganizations(token: string): Promise<any[]> {
156 console.error("No access token provided.");
161 const response = await fetch("https://api.github.com/user/orgs", {
162 headers: { Authorization: `Bearer ${token}` }
165 if (!response.ok) throw new Error(`GitHub API error: ${response.status}`);
167 return await response.json();
169 console.error("Error fetching organizations:", error);
174 export async function renderGithubWidget(
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>`;
186 html += organizations.length ? `</ul>` : "";
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;
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>` : "";
201 <a href="${repo.html_url}" target="_blank">${repo.name}</a>
202 ${fork} | Tags: ${tags} ${description}
207 privateRepos += repoHTML;
210 publicRepos += repoHTML;
215 privateRepos += "</ul>";
216 publicRepos += "</ul>";
218 html += `<h4>Private Repositories (${privateReposCount})</h4>${privateRepos}`;
219 html += `<h4>Public Repositories (${publicReposCount})</h4>${publicRepos}`;
224 export async function injector(widget_name: string, index: number, token: string): Promise<string> {
225 const widgetId = `${widget_name}_${index}`;
226 const listType = "numbered";
228 console.log("injector: token", token);
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);