Skip to content

Commit 8d9c0ae

Browse files
dpswirldrbarker-devandrewb1269
authored
feat: Added github JSON loader and Fixed JS Search (#45)
Signed-off-by: Diogo Pereira <diogo.pereira@swirldslabs.com> Signed-off-by: dpswirld <diogo.pereira@swirldslabs.com> Signed-off-by: Roger Barker <roger.barker@swirldslabs.com> Co-authored-by: Roger Barker <roger.barker@swirldslabs.com> Co-authored-by: Andrew Brandt <andrew.brandt@hashgraph.com>
1 parent 2cfb8c6 commit 8d9c0ae

3 files changed

Lines changed: 102 additions & 87 deletions

File tree

src/static_site_generator.py

Lines changed: 28 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,34 @@
11
from jinja2 import Environment, FileSystemLoader
2+
import logging
23

3-
# Example data
4-
GENERATOR_DATA = {
5-
'title': 'Version Two',
6-
'github_user': 'octocat',
7-
'team': 'Platform Engineering',
8-
'tasks': []
9-
}
104

11-
def generate_site(data=None, output_file='./_site/index.html'):
12-
env = Environment(loader=FileSystemLoader('templates'))
13-
template = env.get_template('kaban_board.html')
5+
class StaticSiteGenerator():
146

15-
GENERATOR_DATA["tasks"] = data if data is not None else []
7+
def __init__(self):
8+
self.GENERATOR_DATA = {
9+
'title': 'Version Two',
10+
'github_user': 'octocat',
11+
'team': 'Platform Engineering',
12+
'tasks': []
13+
}
1614

17-
# Extract unique statuses from the tasks list
18-
unique_statuses = sorted({task["status"] for task in GENERATOR_DATA["tasks"]})
19-
20-
# Add statuses to the data dictionary
21-
data_with_statuses = {**GENERATOR_DATA, "statuses": unique_statuses}
22-
23-
# Render template with updated data
24-
output = template.render(data_with_statuses)
25-
26-
with open(output_file, 'w') as f:
27-
f.write(output)
15+
def generate_site(self, data=None, output_file='./_site/index.html'):
16+
logging.info("Generating Static Site")
17+
env = Environment(loader=FileSystemLoader('templates'))
18+
template = env.get_template('kaban_board.html')
2819

20+
self.GENERATOR_DATA["tasks"] = data if data is not None else []
21+
22+
# Extract unique statuses from the tasks list
23+
unique_statuses = sorted({task["status"] for task in self.GENERATOR_DATA["tasks"]})
24+
25+
# Add statuses to the data dictionary
26+
data_with_statuses = {**self.GENERATOR_DATA, "statuses": unique_statuses}
27+
28+
# Render template with updated data
29+
output = template.render(data_with_statuses)
30+
31+
with open(output_file, 'w') as f:
32+
f.write(output)
33+
34+
logging.info("Static Site Generated @ ./_site/index.html")

templates/kaban_board.html

Lines changed: 68 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -41,88 +41,94 @@ <h1 class="mb-3 text-center">{{ title }}</h1>
4141
<!-- <div class="col-md-4">
4242
<p><strong>Team:</strong> {{ team }}</p>
4343
</div> -->
44-
<div class="col-md-4">
45-
<input type="text" id="searchBox" class="form-control" placeholder="Search tasks...">
44+
<div class="search-bar col-md-4">
45+
<input type="text" id="search-input" class="form-control" placeholder="Search tasks..." />
4646
</div>
47+
4748
</div>
4849
</div>
4950

5051
<div class="container-fluid py-4">
5152
<!-- Kanban Board -->
5253
<div class="row row-cols-1 row-cols-md-5 g-3">
53-
{% set counter = 0 %}
5454
{% for status in statuses %}
55-
<div class="col">
56-
<div class="kanban-column">
57-
<div class="kanban-header text-primary text-center">{{ status }}</div>
58-
{% for task in tasks if task.status == status %}
59-
60-
<div class="kanban-card">
61-
{% set card_id = "card-" ~ status | lower | replace(" ", "-") ~ "-" ~ counter %}
62-
{% set counter = counter + 1 %}
63-
<div class="d-flex align-items-start gap-2">
64-
<a
65-
href="{{ task.content.url }}"
66-
target="_blank"
67-
class="text-primary text-decoration-none fw-bold"
68-
>
69-
🟢 #{{ task.content.number }}
70-
</a>
71-
<a
72-
class="text-dark text-decoration-none fw-bold flex-grow-1"
73-
data-bs-toggle="collapse"
74-
href="#{{ card_id }}"
75-
role="button"
76-
aria-expanded="false"
77-
aria-controls="{{ card_id }}"
78-
>
79-
{{ task.title }}
80-
</a>
55+
<div class="col">
56+
<div class="kanban-column">
57+
<div class="kanban-header text-primary text-center">{{ status }}</div>
58+
59+
{% for task in tasks if task.status == status %}
60+
{% set card_id = "card-" ~ status | lower | replace(" ", "-") ~ "-" ~ loop.index0 %}
61+
62+
<div class="kanban-card">
63+
<div class="d-flex flex-column align-items-start gap-2">
64+
<a
65+
class="text-dark text-decoration-none fw-bold flex-grow-1"
66+
data-bs-toggle="collapse"
67+
href="#{{ card_id }}"
68+
role="button"
69+
aria-expanded="false"
70+
aria-controls="{{ card_id }}"
71+
>
72+
🟢 {{ task.title }}<a
73+
href="{{ task.content.url }}"
74+
target="_blank"
75+
class="fs-8 text-primary text-decoration-none">
76+
(#{{ task.content.number }})</a>
77+
</a>
78+
</div>
79+
<div class="collapse mt-2" id="{{ card_id }}">
80+
<div>
81+
<small>
82+
<strong>📦 Repository:</strong>
83+
<a href="{{ task.repository }}" target="_blank">
84+
{{ task.content.repository }}
85+
</a>
86+
</small>
8187
</div>
82-
<div class="collapse mt-2" id="{{ card_id }}">
83-
<!-- <div><small><strong>Issue #:</strong> {{ task.content.number }}</small></div> -->
84-
<div>
85-
<small>
86-
<strong>📦 Repository:</strong>
87-
<a href="{{ task.repository }}" target="_blank">
88-
{{ task.content.repository }}
89-
</a>
90-
</small>
91-
</div>
92-
<div><small><strong>👤 Assignee:</strong> {{ task.assignees | join(', ') }}</small></div>
93-
<div><small><strong>🏷️ Labels:</strong> {{ task.labels | join(', ') }}</small></div>
94-
<div><small><strong>📌 Status:</strong> {{ task.status }}</small></div>
95-
<div class="text-center">
96-
<a href="{{ task.content.url }}" target="_blank" class="btn btn-sm btn-outline-primary mt-2">View Issue</a>
97-
</div>
88+
<div><small><strong>👤 Assignee:</strong> {{ task.assignees | join(', ') }}</small></div>
89+
<div><small><strong>🏷️ Labels:</strong> {{ task.labels | join(', ') }}</small></div>
90+
<div><small><strong>📌 Status:</strong> {{ task.status }}</small></div>
91+
<div class="text-center">
92+
<a href="{{ task.content.url }}" target="_blank" class="btn btn-sm btn-outline-primary mt-2">View Issue</a>
9893
</div>
9994
</div>
100-
{% endfor %}
10195
</div>
96+
{% endfor %}
10297
</div>
103-
{% endfor %}
98+
</div>
99+
{% endfor %}
104100
</div>
105101
</div>
106102

107103

108104

109105

110-
<script>
111-
document.addEventListener("DOMContentLoaded", function () {
112-
const searchInput = document.querySelector("#searchBox");
113-
114-
searchInput.addEventListener("input", function () {
115-
const searchTerm = this.value.toLowerCase();
116-
const cards = document.querySelectorAll(".kanban-card");
117-
118-
cards.forEach(card => {
119-
const title = card.querySelector("strong").textContent.toLowerCase();
120-
const description = card.querySelector("small").textContent.toLowerCase();
121-
122-
if (title.includes(searchTerm) || description.includes(searchTerm)) {
123-
card.style.display = "block";
106+
<script>
107+
document.addEventListener("DOMContentLoaded", function() {
108+
// Get the search input and all Kanban cards
109+
const searchInput = document.getElementById('search-input');
110+
const kanbanCards = document.querySelectorAll('.kanban-card');
111+
112+
// Add an event listener for the search input
113+
searchInput.addEventListener('input', function() {
114+
const query = searchInput.value.toLowerCase(); // Get the lowercase version of the query
115+
116+
// Iterate over all the cards
117+
kanbanCards.forEach(function(card) {
118+
// Get the card's title, issue number, and other text content to check if it matches the query
119+
const title = card.querySelector('.d-flex .text-dark').textContent.toLowerCase();
120+
const issueNumber = card.querySelector('.d-flex .text-primary').textContent.toLowerCase();
121+
const repository = card.querySelector('.text-muted') ? card.querySelector('.text-muted').textContent.toLowerCase() : '';
122+
const assignee = card.querySelector('.d-flex .assignee') ? card.querySelector('.d-flex .assignee').textContent.toLowerCase() : '';
123+
124+
// Check if the query matches any part of the task (title, issue number, repository, assignee)
125+
const matches = title.includes(query) || issueNumber.includes(query) || repository.includes(query) || assignee.includes(query);
126+
127+
// Show or hide the card based on the search query match
128+
if (matches) {
129+
card.style.display = 'block'; // Show the card
124130
} else {
125-
card.style.display = "none";
131+
card.style.display = 'none'; // Hide the card
126132
}
127133
});
128134
});

version2.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
from src.version2config import VersionTwoConfig
22
from src.version2query import Version2Query
3-
from src.static_site_generator import generate_site
3+
from src.static_site_generator import StaticSiteGenerator
44
from pathlib import Path
55
import json
6+
import logging
67

78
def main():
89
config:VersionTwoConfig = VersionTwoConfig()
@@ -12,18 +13,20 @@ def main():
1213
teams:list[str] = config.include_team
1314

1415
query:VersionTwoQuery = Version2Query(temp_dir=temp_dir, output_file=output_file)
16+
ss_gen = StaticSiteGenerator()
1517

1618
# Generate output_file or die
19+
logging.info("Querying GitHub API...")
1720
if not query.process(teams):
18-
print("Failed to process query.")
21+
logging.error("Failed to process query.")
1922
return
2023

2124
# Get json object
2225
data = None
2326
with open(output_file, 'r') as f:
2427
data = json.load(f)
2528

26-
generate_site(data=data)
29+
ss_gen.generate_site(data=data)
2730

2831
if __name__ == "__main__":
2932
main()

0 commit comments

Comments
 (0)