Skip to content

Commit

Permalink
refactor issue-finder.js to remove vue and simplify with plain js; up…
Browse files Browse the repository at this point in the history
…dated issue-finder.html
  • Loading branch information
Queen-codes committed Dec 30, 2024
1 parent 640995f commit e342403
Show file tree
Hide file tree
Showing 2 changed files with 223 additions and 38 deletions.
82 changes: 50 additions & 32 deletions themes/vocabulary_theme/templates/issue_finder.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,40 +3,58 @@
{% block title %}{{ this.title }}{% endblock %}

{% block body %}
<div class="issue-finder">
<div class="header">
<div class="container is-paddingless">
<h1>{{ this.title }}</h1>
<div class="description column is-9 is-paddingless">
{{ this.description }}

<header>
<h1>{{ this.title }}</h1>
<p> {{ this.description }}</p>
</header>
<div>
<div id="app">
<div>
<div class="columns">
<!-- Filters Section -->
<div class="column is-one-quarter">
<form id="filters">
<label for="aim">
<strong>Aim</strong><br />
I am interested in...
</label>
<select id="aim">
<option value="contribute">Contributing code</option>
<option value="triage">Triaging issues</option>
<option value="label">Labelling issues</option>
</select>
<br />
<div id="skill-filters">
<label for="skills">
<strong>Skill set*</strong><br />
Choose up to three skills.
</label>
<select id="skills" multiple>
<!-- Skills dynamically injected -->
</select>
<br />
<label for="experience">
<strong>Experience</strong><br />
Is this your first time contributing to CC?
</label>
<select id="experience">
<option value="beginner">Yes, it is</option>
<option value="experienced" selected>No, it isn’t</option>
</select>
</div>
<p>
*Not all issues have skills marked on them, especially if they are simple issues that do not require proficiency in any specific framework or language. Those issues will not appear when filtering by skill.
</p>
</form>
</div>

<!-- Issues Section -->
<div class="column" id="issues-container">
<p class="no-results">Loading issues...</p>
</div>
</div>
</div>
</div>
<div class="body container">
<div id="vue-app">
{{ this.body }}
<noscript>
The issue finder requires JavaScript. You can try searching on GitHub
using the links below.
<ul class="gh-links">
<li>
<a href="https://github.com/search?q=org%3Acreativecommons+is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22+-linked%3Apr">
issues labeled "good first issue"
</a>
</li>
<li>
<a href="https://github.com/search?q=org%3Acreativecommons+is%3Aissue+is%3Aopen+label%3A%22help+wanted%22+-linked%3Apr">issues
labeled "help wanted"
</a>
</li>
<li>
<a href="https://github.com/search?q=org%3Acreativecommons+is%3Apr+is%3Aopen+label%3A%22help+wanted%22">
PRs labeled "help wanted"
</a>
</li>
</ul>
</noscript>
</div>
</div>
</div>
{% endblock %}
179 changes: 173 additions & 6 deletions webpack/js/issue-finder.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,174 @@
import Vue from 'vue';
import {App} from './components'
import { Octokit } from "@octokit/rest"; // GitHub API
import yaml from "js-yaml"; // Parse YAML files into JS objects

$(document).ready(function () {
if (window.location.pathname == '/contributing-code/issue-finder/')
window.app = new Vue(App)
})
// Wait for the DOM to fully load before running the script
document.addEventListener("DOMContentLoaded", function () {
// HTML element references
const issuesContainer = document.getElementById("issues-container");
const aimDropdown = document.getElementById("aim");
const skillsDropdown = document.getElementById("skills");
const experienceDropdown = document.getElementById("experience");
const skillFiltersDiv = document.getElementById("skill-filters");

// Base URL for fetching YAML data
const BASE_YAML_URL =
"https://raw.githubusercontent.com/creativecommons/ccos-scripts/main/ccos/norm";
const getYamlFileUrl = (fileName) => `${BASE_YAML_URL}/${fileName}.yml`;

// Initial state for issues and filters
let issuesList = []; //
const userFilters = {
aim: "contribute", // Default to "Contribute"
skills: [], // Default to "No preferences"
experience: "experienced", // Default to "Experienced"
};

// Fetch and load filter data (skills and labels)
async function fetchFilterData() {
try {
const [skillsYaml, labelsYaml] = await Promise.all([
fetch(getYamlFileUrl("skills")).then((res) => res.text()),
fetch(getYamlFileUrl("labels")).then((res) => res.text()),
]);

const skills = yaml.safeLoad(skillsYaml);
populateSkillsDropdown(Object.values(skills).flat()); // Populate skills dropdown
} catch (error) {
console.error("Error loading filters:", error);
}
}

// Populate the skills dropdown with options
function populateSkillsDropdown(skillsArray) {
skillsDropdown.innerHTML = ""; // Clear existing options
const noPreferenceOption = document.createElement("option");
noPreferenceOption.value = ""; // Empty value for "No preferences"
noPreferenceOption.textContent = "No preferences";
skillsDropdown.appendChild(noPreferenceOption);

// Add a dropdown option for each skill
skillsArray.forEach((skill) => {
const optionElement = document.createElement("option");
optionElement.value = skill.toLowerCase();
optionElement.textContent = skill;
skillsDropdown.appendChild(optionElement);
});
}

// Build GitHub search query based on user-selected filters
function loadIssues() {
const query = ["org:creativecommons", "is:open", "is:issue"];

if (userFilters.aim === "contribute") query.push('label:"help wanted"');
if (userFilters.aim === "triage")
query.push('label:"🚦 status: awaiting triage"');
if (userFilters.aim === "label")
query.push('label:"🏷 status: label work required"');

return query.join(" ");
}

// Fetch and display GitHub issues based on filters
async function fetchAndDisplayIssues() {
try {
const octokit = new Octokit();
const query = loadIssues();
const response = await octokit.search.issuesAndPullRequests({
q: query,
per_page: 100,
sort: "created",
order: "desc",
});

// Extract needed data from issues
issuesList = response.data.items.map((issue) => ({
...issue,
labels: issue.labels.map((label) => label.name),
repo: issue.repository_url.split("/").pop(),
}));

displayFilteredIssues(); // Display filtered issues
} catch (error) {
console.error("Error loading GitHub issues:", error);
}
}

// function to display filtered issues
function displayFilteredIssues() {
issuesContainer.innerHTML = ""; // Clear any existing issues

const filteredIssues = issuesList.filter((issue) => {
if (userFilters.aim !== "contribute") return true;

// Show only "good first issues" for beginners
if (
userFilters.experience === "beginner" &&
!issue.labels.includes("good first issue")
)
return false;

// Check if issue matches selected skills
if (
userFilters.skills.length &&
!userFilters.skills.some((skill) =>
issue.labels.includes(`💪 skill: ${skill}`)
)
)
return false;

return true; // Show issue if it meets all criteria
});

// Show "No results" message if no issues match
if (filteredIssues.length === 0) {
issuesContainer.innerHTML = "<p>No results.</p>";
return;
}

// Create an issue card for each filtered issue
filteredIssues.forEach((issue) => {
const issueCard = document.createElement("div");
issueCard.className = "issue-card";
issueCard.innerHTML = `
<h4>${issue.title}</h4>
<p>
<a href="${issue.html_url}" target="_blank">
<span>${issue.repo}#${issue.number}</span>
</a>
opened on ${issue.created_at.split("T")[0]}.
</p>
<div class="labels">
${issue.labels
.map((label) => `<span class="label">${label}</span>`)
.join("")}
</div>
`;
issuesContainer.appendChild(issueCard);
});
}

// Update filters and reload issues when the user changes selections
aimDropdown.addEventListener("change", (event) => {
userFilters.aim = event.target.value;
skillFiltersDiv.style.display =
userFilters.aim === "contribute" ? "block" : "none";
fetchAndDisplayIssues();
});

skillsDropdown.addEventListener("change", (event) => {
const selectedSkills = Array.from(event.target.selectedOptions).map(
(option) => option.value
);
userFilters.skills = selectedSkills.includes("") ? [] : selectedSkills;
displayFilteredIssues();
});

experienceDropdown.addEventListener("change", (event) => {
userFilters.experience = event.target.value;
displayFilteredIssues();
});

// Load filters and issues when the page loads
fetchFilterData();
fetchAndDisplayIssues();
});

0 comments on commit e342403

Please sign in to comment.