From 5b9dd13010f765b90c13870216fbc506f39ddea1 Mon Sep 17 00:00:00 2001 From: Antal Orcsik Date: Tue, 27 Feb 2024 00:47:12 +0100 Subject: [PATCH] tag factory --- src/css/changelog.css | 4 ++ src/js/changelog-topic.js | 43 ++++++----------- src/js/changelog/ChangelogList.js | 61 +++---------------------- src/js/changelog/ChangelogTagFactory.js | 61 +++++++++++++++++++++++++ src/js/changelog/ChangelogTopic.js | 32 ++++++++++++- 5 files changed, 116 insertions(+), 85 deletions(-) create mode 100644 src/js/changelog/ChangelogTagFactory.js diff --git a/src/css/changelog.css b/src/css/changelog.css index b04ff12..5c8f9a0 100644 --- a/src/css/changelog.css +++ b/src/css/changelog.css @@ -7,6 +7,10 @@ display: inline; } +.changelog-tag-placeholder { + display: none; +} + .changelog-topic-content .meta { display: none; } diff --git a/src/js/changelog-topic.js b/src/js/changelog-topic.js index 9ec6ac0..70b12f3 100644 --- a/src/js/changelog-topic.js +++ b/src/js/changelog-topic.js @@ -1,4 +1,5 @@ import ChangelogService from "./changelog/ChangelogService"; +import ChangelogTagFactory from "./changelog/ChangelogTagFactory"; import { formatDate, loadCss } from "./common"; loadCss(require("../css/changelog.css")); @@ -16,34 +17,11 @@ function detectTopicFromUrl(url) { return null; } -class ChangelogTopicDetails -{ - constructor() { - /** @type {HTMLDivElement} */ - this.tagPurpleFilledTemplate = document.querySelector("#changelog-tag-purple-filled"); - this.tagPurpleFilledTemplate.id = ""; - this.tagPurpleFilledTemplate.remove(); +const tagFactory = new ChangelogTagFactory(); - /** @type {HTMLDivElement} */ - this.tagPurpleTemplate = document.querySelector("#changelog-tag-purple"); - this.tagPurpleTemplate.id = ""; - this.tagPurpleTemplate.remove(); - - /** @type {HTMLDivElement} */ - this.tagBlueTemplate = document.querySelector("#changelog-tag-blue"); - this.tagBlueTemplate.id = ""; - this.tagBlueTemplate.remove(); - - /** @type {HTMLDivElement} */ - this.tagYelowTemplate = document.querySelector("#changelog-tag-yellow"); - this.tagYelowTemplate.id = ""; - this.tagYelowTemplate.remove(); - - /** @type {HTMLDivElement} */ - this.topicMetaSeparator = document.querySelector("#changelog-topic-meta-separator"); - this.topicMetaSeparator.style.display = "none"; - } -} +/** @type {HTMLDivElement} */ +const topicMetaSeparator = document.querySelector("#changelog-topic-meta-separator"); +topicMetaSeparator.style.display = "none"; const url = new URL(document.location.href); const topicSlugId = detectTopicFromUrl(url); @@ -52,8 +30,6 @@ const topicSlugId = detectTopicFromUrl(url); const apiBase = document.location.hostname.match(/(localhost|127\.0\.0\.1)/) ? "" : "https://bitrise.io"; const changelogService = new ChangelogService(apiBase); -const changelogTopicDetails = new ChangelogTopicDetails(); - document.getElementById("changelog-topic-title").innerHTML = "Loading"; document.getElementById("changelog-topic-meta").innerHTML = "Loading"; document.getElementById("changelog-topic-content").innerHTML = @@ -65,7 +41,14 @@ changelogService.loadTopic(topicSlugId).then(topic => { document.getElementById("changelog-topic-title").innerHTML = topic.fancyTitle; document.getElementById("changelog-topic-meta").innerHTML = formatDate(topic.createdAt); - document.getElementById("changelog-topic-content").innerHTML = topic.posts[0].cooked; + + const listItemTag = tagFactory.getTopicTag(topic.tags); + if (listItemTag) { + document.querySelector(".changelog-tag-placeholder").replaceWith(listItemTag); + topicMetaSeparator.style.display = "block"; + } + + document.getElementById("changelog-topic-content").innerHTML = topic.content; document.querySelectorAll("#changelog-topic-content .lightbox-wrapper").forEach(lightboxWrapper => { const image = lightboxWrapper.querySelector("img"); diff --git a/src/js/changelog/ChangelogList.js b/src/js/changelog/ChangelogList.js index 6e23010..214d5ac 100644 --- a/src/js/changelog/ChangelogList.js +++ b/src/js/changelog/ChangelogList.js @@ -1,5 +1,6 @@ import { formatDate } from "../common"; -import ChangelogTopic, { ChangelogTag } from "./ChangelogTopic"; +import ChangelogTagFactory from "./ChangelogTagFactory"; +import ChangelogTopic from "./ChangelogTopic"; class ChangelogList { @@ -7,25 +8,7 @@ class ChangelogList /** @type {HTMLUListElement} */ this.list = list; - /** @type {HTMLDivElement} */ - this.tagPurpleFilledTemplate = this.list.querySelector("#changelog-tag-purple-filled"); - this.tagPurpleFilledTemplate.id = ""; - this.tagPurpleFilledTemplate.remove(); - - /** @type {HTMLDivElement} */ - this.tagPurpleTemplate = this.list.querySelector("#changelog-tag-purple"); - this.tagPurpleTemplate.id = ""; - this.tagPurpleTemplate.remove(); - - /** @type {HTMLDivElement} */ - this.tagBlueTemplate = this.list.querySelector("#changelog-tag-blue"); - this.tagBlueTemplate.id = ""; - this.tagBlueTemplate.remove(); - - /** @type {HTMLDivElement} */ - this.tagYelowTemplate = this.list.querySelector("#changelog-tag-yellow"); - this.tagYelowTemplate.id = ""; - this.tagYelowTemplate.remove(); + this.tagFactory = new ChangelogTagFactory(); /** @type {HTMLLIElement} */ this.unreadListItemTemplate = this.list.querySelector("#changelog-unread-template"); @@ -63,49 +46,19 @@ class ChangelogList return timestampListItem; } - /** - * @param {ChangelogTag[]} tags - * @returns {HTMLDivElement?} - */ - getTopicTag(tags) { - if (tags.includes("new-feature")) { - const listItemTag = this.tagPurpleFilledTemplate.cloneNode(true); - listItemTag.innerHTML = `🎉 New feature`; - return listItemTag; - } - else if (tags.includes("feature-update")) { - const listItemTag = this.tagPurpleTemplate.cloneNode(true); - listItemTag.innerHTML = 'Feature update'; - return listItemTag; - } - else if (tags.includes("step-update")) { - const listItemTag = this.tagBlueTemplate.cloneNode(true); - listItemTag.innerHTML = 'Step update'; - return listItemTag; - } - else if (tags.includes("deprecation")) { - const listItemTag = this.tagYelowTemplate.cloneNode(true); - listItemTag.innerHTML = 'Deprecation'; - return listItemTag; - } - return null; - } - /** * @param {ChangelogTopic} topic * @param {boolean} isUnread * @returns {HTMLLIElement} */ renderListItem(topic, isUnread = false) { + /** @type {HTMLLIElement} */ const listItem = (isUnread ? this.unreadListItemTemplate : this.readListItemTemplate).cloneNode(true); listItem.querySelector(".changelog-timestamp").innerHTML = formatDate(topic.createdAt); - - /** @type {HTMLDivElement} */ - const changelogTitleElement = listItem.querySelector(".changelog-title"); - changelogTitleElement.innerHTML = topic.fancyTitle; + listItem.querySelector(".changelog-title").innerHTML = topic.fancyTitle; - const listItemTag = this.getTopicTag(topic.tags); - if (listItemTag) changelogTitleElement.parentNode.insertBefore(listItemTag, changelogTitleElement); + const listItemTag = this.tagFactory.getTopicTag(topic.tags); + if (listItemTag) listItem.querySelector(".changelog-tag-placeholder").replaceWith(listItemTag); listItem.querySelector("a").href = topic.webflowUrl; return listItem; diff --git a/src/js/changelog/ChangelogTagFactory.js b/src/js/changelog/ChangelogTagFactory.js new file mode 100644 index 0000000..b4821b9 --- /dev/null +++ b/src/js/changelog/ChangelogTagFactory.js @@ -0,0 +1,61 @@ +import { ChangelogTag } from "./ChangelogTopic"; + +class ChangelogTagFactory +{ + constructor() { + this.tagPurpleFilledTemplate = this.initTag("#changelog-tag-purple-filled"); + this.tagPurpleTemplate = this.initTag("#changelog-tag-purple"); + this.tagBlueTemplate = this.initTag("#changelog-tag-blue"); + this.tagYelowTemplate = this.initTag("#changelog-tag-yellow"); + } + + /** + * + * @param {string} id + * @returns {HTMLDivElement} + */ + initTag(id) { + /** @type {HTMLDivElement} */ + const tag = document.querySelector(id); + + /** @type {HTMLDivElement} */ + const tagTemplate = tag.cloneNode(true); + tagTemplate.id = ""; + + const tagPlaceholder = document.createElement("div"); + tagPlaceholder.className = "changelog-tag-placeholder"; + tag.replaceWith(tagPlaceholder); + + return tagTemplate; + } + + /** + * @param {ChangelogTag[]} tags + * @returns {HTMLDivElement?} + */ + getTopicTag(tags) { + if (tags.includes("new-feature")) { + const listItemTag = this.tagPurpleFilledTemplate.cloneNode(true); + listItemTag.innerHTML = `🎉 New feature`; + return listItemTag; + } + else if (tags.includes("feature-update")) { + const listItemTag = this.tagPurpleTemplate.cloneNode(true); + listItemTag.innerHTML = 'Feature update'; + return listItemTag; + } + else if (tags.includes("step-update")) { + const listItemTag = this.tagBlueTemplate.cloneNode(true); + listItemTag.innerHTML = 'Step update'; + return listItemTag; + } + else if (tags.includes("deprecation")) { + const listItemTag = this.tagYelowTemplate.cloneNode(true); + listItemTag.innerHTML = 'Deprecation'; + return listItemTag; + } + return null; + } +} + +export default ChangelogTagFactory; \ No newline at end of file diff --git a/src/js/changelog/ChangelogTopic.js b/src/js/changelog/ChangelogTopic.js index ada9aa6..34d20b3 100644 --- a/src/js/changelog/ChangelogTopic.js +++ b/src/js/changelog/ChangelogTopic.js @@ -1,8 +1,32 @@ /** @typedef {("new-feature" | "feature-update" | "step-update" | "deprecation")} ChangelogTag */ +/** + * @typedef {{ + * id: number, + * title: string, + * fancy_title: string, + * slug: string, + * created_at: string, + * pinned: boolean, + * tags: string[], + * post_stream: { + * posts: DiscoursePost[] + * } + * }} DiscourseTopic + */ + +/** + * @typedef {{ + * id: number, + * cooked: string + * }} DiscoursePost + */ + class ChangelogTopic { + /** @param {DiscourseTopic} data */ constructor(data) { + /** @type {DiscourseTopic} */ this.data = data; } @@ -36,6 +60,7 @@ class ChangelogTopic return !!this.data.pinned; } + /** @returns {DiscoursePost[]} */ get posts() { if (this.data.post_stream) { return this.data.post_stream.posts; @@ -43,9 +68,14 @@ class ChangelogTopic return []; } + /** @returns {string} */ + get content() { + return this.posts.length ? this.posts[0].cooked : ""; + } + /** @returns {ChangelogTag[]} */ get tags() { - return this.data.tags || []; + return (this.data.tags || []).filter((tag) => ["new-feature", "feature-update", "step-update", "deprecation"].includes(tag)); } }