Skip to content

Load issues dynamically in the Issue Finder #543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 29, 2020
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions themes/vocabulary_theme/templates/issue_finder.html
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,4 @@ <h1>{{ this.title }}</h1>
</div>
</div>
</div>
<script>
// Transfer all issues to the JavaScript domain
window.issues =
{{ bag('issues.issues')|tojson }}
</script>
{% endblock %}
76 changes: 66 additions & 10 deletions webpack/js/components.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import VueSelect from 'vue-select';
import {Octokit} from '@octokit/rest';

import {hydrateAppWithData} from "./hydration";

Expand Down Expand Up @@ -40,7 +41,7 @@ export const IssueCard = {
</h4>
<p class="is-size-6">
<a
:href="issue.url"
:href="issue.html_url"
target="_blank">
<span class="has-color-forest-green">
{{ issue.repo }}#{{ issue.number }}
Expand Down Expand Up @@ -70,8 +71,7 @@ export const IssueCard = {
},
computed: {
dateCreated() {
const dateCreated = new Date(this.issue.createdAt * 1000)
const [dateComponent,] = dateCreated.toISOString().split("T")
const [dateComponent,] = this.issue.created_at.split("T")
return dateComponent
}
}
Expand All @@ -84,6 +84,20 @@ export const App = {
<div class="columns">
<div class="column is-one-quarter">
<form id="filters" v-if="options.skills.length">
<label for="aim">
<strong>Aim</strong><br/>
I am interested in...
</label>
<VueSelect
v-model="filters.aim"
id="aim"
name="aim"
:options="options.aims"
label="name"
:reduce="aim => aim.code"
:clearable="false"/>
<br/>
<template v-if="filters.aim === 'contribute'">
<label for="skills">
<strong>Skill set*</strong><br/>
Choose up to three skills that you would like to see issues for.
Expand All @@ -110,6 +124,7 @@ export const App = {
label="name"
:reduce="experience => experience.code"
:clearable="false"/>
</template>
</form>
<p class="disclaimer">
*Not all issues have skills marked on them, especially if they are
Expand Down Expand Up @@ -144,18 +159,24 @@ export const App = {
data() {
return {
options: {
aims: [
{name: 'Contributing code', code: 'contribute'},
{name: 'Triaging issues', code: 'triage'}
],
skills: [],
experiences: [
{name: 'Yes, it is', code: 'beginner'},
{name: 'No, it isn\'t', code: 'experienced'}
]
},
filters: {
aim: 'contribute',
skills: [],
experience: 'experienced'
},
categories: {},
issues: []
issues: [],
octokit: null
}
},
computed: {
Expand All @@ -165,26 +186,61 @@ export const App = {
* @returns {array} the array of filtered issues
*/
filteredIssues() {
return window.issues.filter(issue => {
return this.issues.filter(issue => {
// If aim is to triage issues
if (this.filters.aim === 'triage') {
// Show all issues as they all have the label "🚦 status: awaiting triage"
return true
}

// Check experience match
if (this.filters.experience === 'beginner' && !issue.labels.includes('good first issue')) {
return false
}

// Check skill set match
const joinedLabels = issue.labels.join(',')
if (this.filters.skills.length && !this.filters.skills.some(skill => joinedLabels.includes(skill))) {
return false
}

return true
return !(this.filters.skills.length && !this.filters.skills.some(skill => joinedLabels.includes(skill)));
}).sort((a, b) => b.createdAt - a.createdAt)
}
},
watch: {
'filters.aim' (to, from) {
if (to !== from) {
this.loadIssues()
}
}
},
methods: {
loadIssues () {
const q = ['org:creativecommons', 'is:open', 'is:issue']
if (this.filters.aim === 'contribute') {
q.push('label:"help wanted"')
} else if (this.filters.aim === 'triage') {
q.push('label:"🚦 status: awaiting triage"')
}
this.octokit.search.issuesAndPullRequests({
q: q.join(' '),
per_page: 100,
sort: 'updated'
}).then(res => {
this.issues = res.data.items
this.issues.forEach(issue => {
issue.labels = issue.labels.map(label => label.name)

const repoUrl = issue.repository_url
issue.repo = repoUrl.slice(repoUrl.lastIndexOf('/') + 1)
})
})
}
},
mounted() {
const BASE_URL = 'https://raw.githubusercontent.com/creativecommons/ccos-scripts/master/normalize_repos'
const FILE_URL = name => `${BASE_URL}/${name}.json`

this.octokit = new Octokit()
this.loadIssues()

Promise
.all([
fetch(FILE_URL('skills'))
Expand Down
17 changes: 10 additions & 7 deletions webpack/js/hydration.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
export const hydrateAppWithData = (skills, labels) => {
skills = Array.from( // Convert back into an array
new Set( // Remove duplicates
Object.values(skills)
.flat() // Combine all skills
.map(skill => skill.split('/')[0]) // Keep only the prefix
)
skills = Array.from(
new Set( // Remove duplicates
Object.values(skills).flat() // Combine all skills
)
)
const top_level_skills = Array.from(
new Set( // Remove duplicates
skills.map(skill => skill.split('/')[0]) // Keep only the prefix
)
)

const categories = {}
Expand Down Expand Up @@ -35,5 +38,5 @@ export const hydrateAppWithData = (skills, labels) => {
categories[name] = 'skill'
})

return [skills, categories]
return [top_level_skills, categories]
}
150 changes: 147 additions & 3 deletions webpack/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions webpack/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
"webpack-cli": "^3.3.11"
},
"dependencies": {
"@octokit/rest": "^18.0.6",
"vue": "^2.6.12",
"vue-select": "^3.10.8"
},
Expand Down