Skip to content

Commit 26e046e

Browse files
feat(pages): add roadmap page
1 parent 0768394 commit 26e046e

File tree

6 files changed

+271
-1
lines changed

6 files changed

+271
-1
lines changed

_config_theme.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ navbar-links:
1818
- Status: "https://status.LizardByte.dev"
1919
Development:
2020
- Contributing: "https://docs.lizardbyte.dev/latest/developers/contributing.html"
21+
- Roadmap: "roadmap"
2122
- Dashboard: "https://app.lizardbyte.dev/dashboard"
2223
- Dev Status: "https://status-dev.LizardByte.dev"
2324
avatar: "/assets/img/navbar-avatar.png"

_sass/styles.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ body {
2020
background-color: var(--navbar-col) !important;
2121
}
2222

23+
.modal-content {
24+
background-color: var(--footer-col) !important;
25+
}
26+
2327
/* in line code */
2428
code {
2529
color: var(--mid-col);

assets/img/banners/roadmap.jpg

187 KB
Loading

assets/js/projects.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// projects section script
22

33
// get project container
4-
container = document.getElementById("project-container")
4+
let container = document.getElementById("project-container")
55
let org_name = "LizardByte"
66
let base_url = `https://app.${org_name.toLowerCase()}.dev`
77
let cache_repo = "dashboard"

assets/js/roadmap.js

Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
document.addEventListener('DOMContentLoaded', function() {
2+
const issuesList = document.getElementById('issues-container');
3+
const issueModal = new bootstrap.Modal(document.getElementById('issueModal'));
4+
const issueModalBody = document.getElementById('issueModalBody');
5+
const issueModalLabel = document.getElementById('issueModalLabel');
6+
const viewOnGithubBtn = document.getElementById('viewOnGithub');
7+
8+
// GitHub API endpoint for your repository's issues
9+
const apiUrl = 'https://api.github.com/repos/LizardByte/roadmap/issues?state=open&labels=planned&per_page=100';
10+
11+
fetch(apiUrl)
12+
.then(response => {
13+
if (!response.ok) {
14+
throw new Error('Network response was not ok');
15+
}
16+
return response.json();
17+
})
18+
.then(issues => {
19+
if (issues.length === 0) {
20+
issuesList.innerHTML = '<p>No roadmap items found.</p>';
21+
return;
22+
}
23+
24+
// Clear loading message
25+
issuesList.innerHTML = '';
26+
27+
issues.forEach(issue => {
28+
const issueCol = document.createElement('div');
29+
issueCol.className = 'col-lg-4 mb-5';
30+
31+
const issueEl = document.createElement('div');
32+
issueEl.className = 'card h-100 shadow border-0 rounded-0';
33+
issueEl.style.cursor = 'pointer';
34+
35+
// Store issue data for modal
36+
issueEl.dataset.issue = JSON.stringify(issue);
37+
38+
// Click event to show modal
39+
issueEl.addEventListener('click', function() {
40+
const issueData = JSON.parse(this.dataset.issue);
41+
displayIssueInModal(issueData);
42+
});
43+
44+
const cardBody = document.createElement('div');
45+
cardBody.className = 'card-body text-white p-4 rounded-0';
46+
47+
// Issue title
48+
const titleEl = document.createElement('h5');
49+
titleEl.className = 'card-title mb-3 fw-bolder crowdin-ignore';
50+
const titleText = document.createElement('span');
51+
titleText.textContent = issue.title;
52+
titleText.className = 'text-decoration-none';
53+
titleEl.appendChild(titleText);
54+
55+
// Issue metadata
56+
const metaEl = document.createElement('div');
57+
metaEl.className = 'd-flex justify-content-between mb-2 small';
58+
59+
// Issue number
60+
const numberEl = document.createElement('span');
61+
numberEl.className = 'badge bg-secondary crowdin-ignore';
62+
numberEl.textContent = `#${issue.number}`;
63+
64+
// Issue date
65+
const dateEl = document.createElement('span');
66+
dateEl.className = 'crowdin-ignore';
67+
const createdDate = new Date(issue.created_at);
68+
dateEl.textContent = createdDate.toLocaleDateString();
69+
70+
metaEl.appendChild(numberEl);
71+
metaEl.appendChild(dateEl);
72+
73+
// Labels
74+
const labelsEl = document.createElement('div');
75+
labelsEl.className = 'd-flex flex-wrap gap-1 mb-2';
76+
77+
// Sort labels alphabetically by name
78+
const sortedLabels = [...issue.labels].sort((a, b) =>
79+
a.name.toLowerCase().localeCompare(b.name.toLowerCase())
80+
);
81+
82+
sortedLabels.forEach(label => {
83+
const labelEl = document.createElement('span');
84+
labelEl.className = 'badge crowdin-ignore';
85+
labelEl.textContent = label.name;
86+
labelEl.style.backgroundColor = `#${label.color}`;
87+
88+
// Determine if label text should be dark or light based on background
89+
const r = parseInt(label.color.substring(0, 2), 16);
90+
const g = parseInt(label.color.substring(2, 4), 16);
91+
const b = parseInt(label.color.substring(4, 6), 16);
92+
const brightness = (r * 299 + g * 587 + b * 114) / 1000;
93+
labelEl.style.color = brightness > 125 ? '#000' : '#fff';
94+
95+
labelsEl.appendChild(labelEl);
96+
});
97+
98+
// Add all elements to the card body
99+
cardBody.appendChild(titleEl);
100+
cardBody.appendChild(metaEl);
101+
cardBody.appendChild(labelsEl);
102+
103+
issueEl.appendChild(cardBody);
104+
issueCol.appendChild(issueEl);
105+
issuesList.appendChild(issueCol);
106+
});
107+
108+
})
109+
.catch(error => {
110+
issuesList.innerHTML = `<p class="text-danger">Error loading roadmap items: ${error.message}</p>`;
111+
});
112+
113+
// Function to display issue in modal
114+
function displayIssueInModal(issue) {
115+
// Set modal title
116+
issueModalLabel.textContent = `${issue.title} (#${issue.number})`;
117+
118+
// Set GitHub link
119+
viewOnGithubBtn.href = issue.html_url;
120+
121+
// Create modal content
122+
let modalContent = document.createElement('div');
123+
124+
// Issue metadata
125+
const metaEl = document.createElement('div');
126+
metaEl.className = 'd-flex justify-content-between mb-3';
127+
128+
// Issue created date
129+
const createdEl = document.createElement('span');
130+
const createdLabel = document.createElement('strong');
131+
createdLabel.textContent = 'Created:';
132+
createdEl.appendChild(createdLabel);
133+
createdEl.appendChild(document.createTextNode(' '));
134+
135+
const createdValue = document.createElement('span');
136+
createdValue.className = 'crowdin-ignore';
137+
const createdDate = new Date(issue.created_at);
138+
createdValue.textContent = createdDate.toLocaleDateString();
139+
createdEl.appendChild(createdValue);
140+
141+
// Issue author
142+
const authorEl = document.createElement('span');
143+
const authorLabel = document.createElement('strong');
144+
authorLabel.textContent = 'By:';
145+
authorEl.appendChild(authorLabel);
146+
authorEl.appendChild(document.createTextNode(' '));
147+
148+
const authorValue = document.createElement('span');
149+
authorValue.className = 'crowdin-ignore';
150+
authorValue.textContent = issue.user.login;
151+
authorEl.appendChild(authorValue);
152+
153+
metaEl.appendChild(createdEl);
154+
metaEl.appendChild(authorEl);
155+
modalContent.appendChild(metaEl);
156+
157+
// Labels
158+
if (issue.labels && issue.labels.length > 0) {
159+
const labelsContainer = document.createElement('div');
160+
labelsContainer.className = 'mb-3';
161+
162+
const labelsTitle = document.createElement('strong');
163+
labelsTitle.textContent = 'Labels:';
164+
labelsContainer.appendChild(labelsTitle);
165+
166+
const labelsEl = document.createElement('div');
167+
labelsEl.className = 'd-flex flex-wrap gap-1 mt-1';
168+
169+
issue.labels.forEach(label => {
170+
const labelEl = document.createElement('span');
171+
labelEl.className = 'badge crowdin-ignore';
172+
labelEl.textContent = label.name;
173+
labelEl.style.backgroundColor = `#${label.color}`;
174+
175+
// Determine if label text should be dark or light based on background
176+
const r = parseInt(label.color.substring(0, 2), 16);
177+
const g = parseInt(label.color.substring(2, 4), 16);
178+
const b = parseInt(label.color.substring(4, 6), 16);
179+
const brightness = (r * 299 + g * 587 + b * 114) / 1000;
180+
labelEl.style.color = brightness > 125 ? '#000' : '#fff';
181+
182+
labelsEl.appendChild(labelEl);
183+
});
184+
185+
labelsContainer.appendChild(labelsEl);
186+
modalContent.appendChild(labelsContainer);
187+
}
188+
189+
// Issue body
190+
const bodyContainer = document.createElement('div');
191+
bodyContainer.className = 'mt-3 p-3 rounded-0';
192+
193+
if (issue.body) {
194+
// Create a container with crowdin-ignore class for the entire rendered content
195+
const markdownContainer = document.createElement('div');
196+
markdownContainer.className = 'crowdin-ignore';
197+
198+
// Use Marked to parse the markdown
199+
markdownContainer.innerHTML = marked.parse(issue.body);
200+
201+
// Add the rendered content to the body container
202+
bodyContainer.appendChild(markdownContainer);
203+
} else {
204+
const noContentMsg = document.createElement('div');
205+
noContentMsg.textContent = 'No description provided.';
206+
bodyContainer.appendChild(noContentMsg);
207+
}
208+
209+
modalContent.appendChild(bodyContainer);
210+
211+
// Set modal content
212+
issueModalBody.innerHTML = '';
213+
issueModalBody.appendChild(modalContent);
214+
215+
// Show modal
216+
issueModal.show();
217+
}
218+
});

roadmap.html

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
---
2+
title: Roadmap
3+
layout: page
4+
full-width: true
5+
cover-img:
6+
- /assets/img/banners/roadmap.jpg
7+
ext-js:
8+
- https://cdn.jsdelivr.net/npm/[email protected]/marked.min.js
9+
js:
10+
- /assets/js/roadmap.js
11+
---
12+
13+
<!-- Roadmap section-->
14+
<section class="py-5" id="Roadmap">
15+
<div class="container my-5">
16+
<div class="row gx-5" id="issues-container">
17+
<p>Loading roadmap items...</p>
18+
</div>
19+
20+
<div class="row gx-5 justify-content-center mt-4">
21+
<div class="col-lg-8 col-xl-6 text-center">
22+
<a href="https://github.com/LizardByte/roadmap/issues" target="_blank" class="btn btn-outline-light rounded-0">
23+
View All
24+
</a>
25+
</div>
26+
</div>
27+
</div>
28+
</section>
29+
30+
<!-- Modal -->
31+
<div class="modal fade" id="issueModal" tabindex="-1" aria-labelledby="issueModalLabel" aria-hidden="true">
32+
<div class="modal-dialog modal-lg">
33+
<div class="modal-content">
34+
<div class="modal-header">
35+
<h5 class="modal-title" id="issueModalLabel">Issue Details</h5>
36+
<button type="button" class="btn-close" data-bs-dismiss="modal" data-bs-theme="dark" aria-label="Close"></button>
37+
</div>
38+
<div class="modal-body" id="issueModalBody">
39+
<!-- Content will be inserted here dynamically -->
40+
</div>
41+
<div class="modal-footer">
42+
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
43+
<a href="#" class="btn btn-primary" id="viewOnGithub" target="_blank">View on GitHub</a>
44+
</div>
45+
</div>
46+
</div>
47+
</div>

0 commit comments

Comments
 (0)