'use strict'; import { Templater, handleResponse } from './util.js'; export default class Changelog { /** * Fetch and render changelog from GitHub. Clones a template node (table row) * to avoid doubling templating markup in JavaScript. * @param {string} user - GitHub username. * @param {string} repo - Repository to fetch releases from. */ constructor(user, repo) { this.url = `https://api.github.com/repos/${user}/${repo}/releases`; this.template = new Templater('changelog'); this.fetchChangelog() .then(json => this.render(json)) .catch(this.showError.bind(this)); // make sure scroll positions for progress bar etc. are recalculated window.dispatchEvent(new Event('resize')); } fetchChangelog() { return new Promise((resolve, reject) => fetch(this.url) .then(res => handleResponse(res)) .then(json => json.ok ? resolve(json) : reject())) } showError() { this.template.get('error').style.display = 'block'; } /** * Get template section from template row. Hacky, but does make sense. * @param {node} item - Parent element. * @param {string} id - ID of child element, set via data-changelog. */ getField(item, id) { return item.querySelector(`[data-changelog="${id}"]`); } render(json) { this.template.get('table').style.display = 'block'; this.row = this.template.get('item'); this.releases = this.template.get('releases'); this.prereleases = this.template.get('prereleases'); Object.values(json) .filter(release => release.name) .forEach(release => this.renderRelease(release)); this.row.remove(); } /** * Clone the template row and populate with content from API response. * https://developer.github.com/v3/repos/releases/#list-releases-for-a-repository * @param {string} name - Release title. * @param {string} tag (tag_name) - Release tag. * @param {string} url (html_url) - URL to the release page on GitHub. * @param {string} date (published_at) - Timestamp of release publication. * @param {boolean} prerelease - Whether the release is a prerelease. */ renderRelease({ name, tag_name: tag, html_url: url, published_at: date, prerelease }) { const container = prerelease ? this.prereleases : this.releases; const tagLink = `${tag}`; const title = (name.split(': ').length == 2) ? name.split(': ')[1] : name; const row = this.row.cloneNode(true); this.getField(row, 'date').textContent = date.split('T')[0]; this.getField(row, 'tag').innerHTML = tagLink; this.getField(row, 'title').textContent = title; container.appendChild(row); } }