Skip to content

Commit

Permalink
use prebuilt changelog script + loading anims
Browse files Browse the repository at this point in the history
  • Loading branch information
aorcsik committed Feb 7, 2024
1 parent 22fbd89 commit c8607ab
Show file tree
Hide file tree
Showing 10 changed files with 285 additions and 69 deletions.
1 change: 1 addition & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"HTMLSpanElement",
"HTMLUListElement",
"Promise",
"Response",
"URL"
]
}
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ node_modules
yarn-error.log
dist/*.js
.yarn/install-state.gz
changelog.json
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
},
"scripts": {
"build_dev": "./node_modules/.bin/webpack --config webpack.dev.js --progress --color",
"build_prod": "./node_modules/.bin/webpack --config webpack.prod.js"
"build_prod": "./node_modules/.bin/webpack --config webpack.prod.js",
"build_changelog": "node ./src/js/changelog/build.js"
}
}
140 changes: 137 additions & 3 deletions src/css/changelog.css
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,141 @@
display: none;
}

.changelog-topic-content h2 {
.changelog-topic-content h1 {
font-size: 2rem;
margin-top: 1rem;
}
margin-bottom: 1rem;
}

.changelog-topic-content h2 {
font-size: 1.5rem;
margin-bottom: 1rem;
}

.changelog-topic-content h3 {
font-size: 1.25rem;
margin-bottom: 1rem;
}

.changelog-topic-content p {
margin-bottom: 1rem;
}

/* aside.ondebox from discuss */

aside.onebox {
border: 5px solid #e9e9e9;
margin: 1em 0;
padding: 1em;
font-size: 1em;
background: #ffffff;
}
aside.onebox header {
align-items: center;
display: flex;
margin-bottom: 1em;
}
aside.onebox .site-icon {
width: 16px;
height: 16px;
margin-right: 0.5em;
}
aside.onebox header a[href] {
color: #919191;
text-decoration: none;
}
aside.onebox .onebox-body {
clear: both;
}
aside.onebox .onebox-body .aspect-image {
max-height: 170px;
--magic-ratio: calc(var(--aspect-ratio) + 0.15);
width: calc(128px*var(--magic-ratio));
max-width: 20%;
float: left;
margin-right: 1em;
height: auto;
}
aside.onebox .onebox-body .aspect-image img {
height: auto;
}
aside.onebox .onebox-body h3,
aside.onebox .onebox-body h4 {
font-size: 1.15rem;
margin: 0 0 10px 0;
line-height: 1.2;
}

@media only screen and (max-width: 600px) {
aside.onebox .onebox-body .aspect-image {
width: 100%;
max-width: 100%;
max-height: 100%;
margin-bottom: 1rem;
}
}

/* aside.ondebox -- end */

/* skeleton loading */

.changelog-loading {
color: transparent;
background: #dedede;
border-radius: 5px;
position: relative;
overflow: hidden;
}

.changelog-loading:before {
content: "";
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
transform: translateX(-100%);
background-image: linear-gradient(
90deg,
rgba(255, 255, 255, 0) 0,
rgba(255, 255, 255, 0.2) 20%,
rgba(255, 255, 255, 0.5) 60%,
rgba(255, 255, 255, 0) 100%
);
animation: shimmer 5s infinite;
}

@keyframes shimmer {
100% {
transform: translateX(100%);
}
}

.changelog-timestamp .changelog-loading {
width: 100px;
display: inline-block;
}

.changelog-title .changelog-loading {
width: 200px;
display: inline-block;
}

#changelog-topic-title .changelog-loading {
width: 300px;
margin-left: auto;
margin-right: auto;
display: block;
}

#changelog-topic-meta .changelog-loading {
width: 200px;
margin-left: auto;
margin-right: auto;
display: block;
}

#changelog-topic-content .changelog-loading:last-child {
width: 60%;
}

/* skeleton loading -- end */
7 changes: 7 additions & 0 deletions src/js/changelog-topic.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ const topicSlugId = detectTopicFromUrl(url);
const apiBase = document.location.hostname.match(/(localhost|127\.0\.0\.1)/) ? "" : "https://bitrise.io";
const changelogService = new ChangelogService(apiBase);

document.getElementById("changelog-topic-title").innerHTML = "<span class='changelog-loading'>Loading</span>";
document.getElementById("changelog-topic-meta").innerHTML = "<span class='changelog-loading'>Loading</span>";
document.getElementById("changelog-topic-content").innerHTML =
"<p class='changelog-loading'>Loading</p>" +
"<p class='changelog-loading'>Loading</p>" +
"<p class='changelog-loading'>Loading</p>";

changelogService.loadTopic(topicSlugId).then(topic => {

document.getElementById("changelog-topic-title").innerHTML = topic.fancyTitle;
Expand Down
23 changes: 3 additions & 20 deletions src/js/changelog.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,24 +13,7 @@ const changelogList = new ChangelogList(document.getElementById("changelog-list"
/** @type {HTMLAnchorElement} */
const changelogLoadMoreButton = document.getElementById("changelog-load-more-button");

/** */
function loadMore() {
changelogLoadMoreButton.disabled = true;
changelogLoadMoreButton.innerHTML = "Loading...";
changelogService.loadMore().then(topics => {
changelogList.render(topics);
changelogLoadMoreButton.disabled = false;
changelogLoadMoreButton.innerHTML = "Load more...";

if (!changelogService.isMore) {
changelogLoadMoreButton.remove();
}
});
}

changelogLoadMoreButton.addEventListener('click', event => {
event.preventDefault();
loadMore();
changelogLoadMoreButton.remove();
changelogService.loadTopics("/changelog.json").then(topics => {
changelogList.render(topics);
});

loadMore();
13 changes: 13 additions & 0 deletions src/js/changelog/ChangelogList.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,18 @@ class ChangelogList
this.readListItemTemplate = this.list.querySelector("#changelog-read-template");
this.readListItemTemplate.id = "";
this.readListItemTemplate.remove();

this.list.append(this.renderLoadingListItem());
this.list.append(this.renderLoadingListItem());
this.list.append(this.renderLoadingListItem());
}

renderLoadingListItem() {
const listItem = this.readListItemTemplate.cloneNode(true);
listItem.querySelector(".changelog-timestamp").innerHTML = "<span class='changelog-loading'>Loading</span>";
listItem.querySelector(".changelog-title").innerHTML = "<span class='changelog-loading'>Loading</span>";
listItem.querySelectorAll(".display-inline .display-inline").forEach(elem => elem.remove());
return listItem;
}


Expand All @@ -38,6 +50,7 @@ class ChangelogList
* @param {ChangelogTopic[]} topics
*/
render(topics) {
this.list.innerHTML = "";
for (let topic of topics) {
if (!this.listItems[topic.id]) {
const listItem = this.renderListItem(topic);
Expand Down
53 changes: 13 additions & 40 deletions src/js/changelog/ChangelogService.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,56 +8,29 @@ class ChangelogService
constructor(apiBase) {
/** @type {string} */
this.apiBase = apiBase;

/** @type {string} */
this.changelogUrl = "/changelog.json";

/** @type {ChangelogTopic[]} */
this.topics = [];

/** @type {number} */
this.nextPage = 0;
/** @type {number} */
this.currentPage = -1;
}

/** @returns {Promise<ChangelogTopic[]>} */
async loadMore() {
if (this.isMore) {
const url = this.apiBase + this.changelogUrl + "?page=" + this.nextPage;
const response = await fetch(url);
const json = await response.json();

this.currentPage = this.nextPage;

if (json.topic_list.more_topics_url) {
const moreTopicsUrlMatch = json.topic_list.more_topics_url.match(/page=(\d+)/);
this.nextPage = parseInt(moreTopicsUrlMatch[1]);
}

json.topic_list.topics.forEach(data => {
this.topics.push(new ChangelogTopic(data));
});
}

return this.topics;
}

/** @returns {boolean} */
get isMore() {
return this.nextPage > this.currentPage;
/**
* @param {string} changelogUrl
* @returns {Promise<ChangelogTopic[]>}
*/
async loadTopics(changelogUrl) {
const url = this.apiBase + changelogUrl;
const response = await fetch(url);
const json = await response.json();
console.log(json);
return json.topic_list.topics.map(data => new ChangelogTopic(data));
}

/**
* @param {string} topicSlugId
* @returns {Promise<ChangelogTopic>}
*/
async loadTopic(topicSlugId) {
const url = this.apiBase + `/changelog/${topicSlugId}.json`;
const url = this.apiBase + `/changelog/api/t/${topicSlugId}.json`;
const response = await fetch(url);
const data = await response.json();
console.log(data);
return new ChangelogTopic(data);
const json = await response.json();
return new ChangelogTopic(json);
}
}

Expand Down
83 changes: 83 additions & 0 deletions src/js/changelog/build.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
const fs = require('fs');

/**
*
* @param {number} time
* @returns {Promise<void>}
*/
function delay(time) {
return new Promise(resolve => setTimeout(resolve, time));
}

/**
*
* @param {string} category
* @returns {Promise<object>}
*/
async function fetchCategory(category) {
const topics = [];

process.stdout.write(`Fetching ${category}: `);

let nextPage = 0;
while (nextPage !== null) {
await delay(500);

const url = "https://discuss.bitrise.io" + category + "?page=" + nextPage;
const response = await fetch(url);
const json = await response.json();
process.stdout.write(".");

json.topic_list.topics.forEach(topic => {
if (!topic.pinned) {
topics.push({
id: topic.id,
title: topic.title,
fancy_title: topic.fancy_title,
slug: topic.slug,
created_at: topic.created_at
});
}
});

nextPage = null;
if (json.topic_list.more_topics_url) {
const moreTopicsUrlMatch = json.topic_list.more_topics_url.match(/page=(\d+)/);
nextPage = parseInt(moreTopicsUrlMatch[1]);
}
}

process.stdout.write(` \x1b[32mdone\x1b[0m (${topics.length})\n`);

return topics;
}

/** @returns {void} */
async function buildChangelog() {
const topics = [];

const productUpdatesTopics = await fetchCategory("/c/product-updates/42.json");
for (let topic of productUpdatesTopics) topics.push(topic);

const changelogTopics = await fetchCategory("/c/changelog/6.json");
for (let topic of changelogTopics) topics.push(topic);

topics.sort((a, b) => {
const aDate = new Date(a.created_at);
const bDate = new Date(b.created_at);
return bDate.getTime() - aDate.getTime(); // reverse
});

const filename = "./changelog.json";
process.stdout.write(`Writing ${filename}: `);
await fs.promises.writeFile("./changelog.json", JSON.stringify({
timestamp: new Date(),
topic_list: {
topics: topics,
},
}));

process.stdout.write(` \x1b[32mdone\x1b[0m\n`);
}

buildChangelog();
Loading

0 comments on commit c8607ab

Please sign in to comment.