-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
130 lines (106 loc) · 4.53 KB
/
script.js
File metadata and controls
130 lines (106 loc) · 4.53 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
document.addEventListener('DOMContentLoaded', () => {
fetchProjects();
document.getElementById('year').textContent = new Date().getFullYear();
});
const CACHE_KEY = 'far_team_projects_cache';
const CACHE_DURATION = 1000 * 60 * 60;
async function fetchProjects() {
const grid = document.getElementById('project-grid');
const loader = document.getElementById('loader');
const errorMsg = document.getElementById('error-message');
grid.innerHTML = '';
grid.classList.add('hidden');
errorMsg.classList.add('hidden');
loader.classList.remove('hidden');
try {
const cacheddata = localStorage.getItem(CACHE_KEY);
if (cacheddata) {
const { timestamp, data } = JSON.parse(cacheddata);
if (Date.now() - timestamp < CACHE_DURATION) {
console.log('Serving from cache');
renderProjects(data);
loader.classList.add('hidden');
grid.classList.remove('hidden');
return;
}
}
const response = await fetch('https://api.github.com/search/repositories?q=org:FaR-Team&sort=updated&per_page=100');
if (!response.ok) {
if (response.status === 403) {
throw new Error("Rate limit exceeded. Try again later.");
}
throw new Error(`GitHub API Error: ${response.status}`);
}
const data = await response.json();
const projects = data.items;
projects.sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at));
const processedProjects = await processProjects(projects);
localStorage.setItem(CACHE_KEY, JSON.stringify({
timestamp: Date.now(),
data: processedProjects
}));
renderProjects(processedProjects);
loader.classList.add('hidden');
grid.classList.remove('hidden');
} catch (error) {
console.error('Error fetching projects:', error);
loader.classList.add('hidden');
errorMsg.classList.remove('hidden');
const p = errorMsg.querySelector('p');
if (p) p.innerHTML = `${error.message} <button onclick="fetchProjects()">Retry</button>`;
}
}
async function processProjects(projects) {
const promises = projects.map(async project => {
if (!project.has_pages && !project.homepage) return null;
let projectUrl = project.homepage;
if (!projectUrl) {
projectUrl = `https://farteam.com.ar/${project.name}`;
}
let displayName = project.name.replace(/[-_]/g, ' ').replace(/\b\w/g, c => c.toUpperCase());
try {
const contentUrl = `https://raw.githubusercontent.com/${project.full_name}/${project.default_branch}/index.html`;
const resp = await fetch(contentUrl);
if (resp.ok) {
const html = await resp.text();
const match = html.match(/<title>(.*?)<\/title>/i);
if (match && match[1]) {
displayName = match[1].trim();
displayName = displayName.replace(/ - FaR Team$/i, '');
}
}
} catch (e) {
}
return { ...project, projectUrl, displayName };
});
return (await Promise.all(promises)).filter(p => p !== null);
}
function renderProjects(projects) {
const grid = document.getElementById('project-grid');
if (projects.length === 0) {
grid.innerHTML = '<p style="text-align:center; grid-column: 1/-1; color: var(--text-secondary);">No projects found.</p>';
return;
}
projects.forEach(project => {
const description = project.description || "No description provided.";
const language = project.language || "Misc";
const card = document.createElement('div');
card.className = 'card';
card.innerHTML = `
<div class="card-header">
<a href="${project.projectUrl}" target="_blank" class="card-title">${project.displayName}</a>
<span class="language-tag">${language}</span>
</div>
<p class="card-desc">${description}</p>
<div class="card-footer">
<a href="${project.projectUrl}" target="_blank" class="glow-btn">
<i class="fa-solid fa-play"></i> Open Project
</a>
<a href="${project.html_url}" target="_blank" class="repo-link" title="View Source">
<i class="fa-brands fa-github"></i>
</a>
</div>
`;
grid.appendChild(card);
});
}