From 1a3edcaae05a2afa7d9ada4477fd6fa75c2f56f5 Mon Sep 17 00:00:00 2001 From: Julian Holfeld Date: Fri, 27 Aug 2021 21:05:10 +0200 Subject: [PATCH] feat: hide wakatime languages (#1212) * feat: added option to hide languages * feat: recalculate percentages for hidden languages * refactor: reverted langs_count and did some formatting * doc: added hide to readme * feat: make languages var mutable and improve filter logic Co-authored-by: Adrian Kunz * refactor: improve code and added tests Co-authored-by: Adrian Kunz Co-authored-by: Anurag --- api/wakatime.js | 3 + readme.md | 1 + src/cards/top-languages-card.js | 9 ++- src/cards/wakatime-card.js | 78 ++++++++++++------- src/common/utils.js | 2 + .../renderWakatimeCard.test.js.snap | 6 +- tests/renderTopLanguages.test.js | 1 - tests/renderWakatimeCard.test.js | 19 ++++- 8 files changed, 82 insertions(+), 37 deletions(-) diff --git a/api/wakatime.js b/api/wakatime.js index 4bb8fca5d16c0..ebfea81fd79bf 100644 --- a/api/wakatime.js +++ b/api/wakatime.js @@ -3,6 +3,7 @@ const { renderError, parseBoolean, clampValue, + parseArray, CONSTANTS, isLocaleAvailable, } = require("../src/common/utils"); @@ -26,6 +27,7 @@ module.exports = async (req, res) => { locale, layout, langs_count, + hide, api_domain, range, border_radius, @@ -58,6 +60,7 @@ module.exports = async (req, res) => { custom_title, hide_title: parseBoolean(hide_title), hide_border: parseBoolean(hide_border), + hide: parseArray(hide), line_height, title_color, icon_color, diff --git a/readme.md b/readme.md index ebc0e8eb6a38c..68265513ccb96 100644 --- a/readme.md +++ b/readme.md @@ -212,6 +212,7 @@ You can provide multiple comma-separated values in bg_color option to render a g #### Wakatime Card Exclusive Options: +- `hide` - Hide the languages specified from the card _(Comma-separated values)_ - `hide_title` - _(boolean)_ - `line_height` - Sets the line-height between text _(number)_ - `hide_progress` - Hides the progress bar and percentage _(boolean)_ diff --git a/src/cards/top-languages-card.js b/src/cards/top-languages-card.js index f281b12567239..701c8c0d46bb9 100644 --- a/src/cards/top-languages-card.js +++ b/src/cards/top-languages-card.js @@ -2,15 +2,18 @@ const Card = require("../common/Card"); const I18n = require("../common/I18n"); const { langCardLocales } = require("../translations"); const { createProgressNode } = require("../common/createProgressNode"); -const { clampValue, getCardColors, flexLayout } = require("../common/utils"); +const { + clampValue, + getCardColors, + flexLayout, + lowercaseTrim, +} = require("../common/utils"); const DEFAULT_CARD_WIDTH = 300; const DEFAULT_LANGS_COUNT = 5; const DEFAULT_LANG_COLOR = "#858585"; const CARD_PADDING = 25; -const lowercaseTrim = (name) => name.toLowerCase().trim(); - const createProgressTextNode = ({ width, color, name, progress }) => { const paddingRight = 95; const progressTextX = width - paddingRight + 10; diff --git a/src/cards/wakatime-card.js b/src/cards/wakatime-card.js index 5e12cf3910d19..54093ec0302e3 100644 --- a/src/cards/wakatime-card.js +++ b/src/cards/wakatime-card.js @@ -4,7 +4,12 @@ const { getStyles } = require("../getStyles"); const { wakatimeCardLocales } = require("../translations"); const languageColors = require("../common/languageColors.json"); const { createProgressNode } = require("../common/createProgressNode"); -const { clampValue, getCardColors, flexLayout } = require("../common/utils"); +const { + clampValue, + getCardColors, + flexLayout, + lowercaseTrim, +} = require("../common/utils"); const noCodingActivityNode = ({ color, text }) => { return ` @@ -61,34 +66,47 @@ const createTextNode = ({ const cardProgress = hideProgress ? null : createProgressNode({ - x: 110, - y: 4, - progress: percent, - color: progressBarColor, - width: 220, - name: label, - progressBarBackgroundColor, - }); + x: 110, + y: 4, + progress: percent, + color: progressBarColor, + width: 220, + name: label, + progressBarBackgroundColor, + }); return ` - ${label}: + ${label}: ${value} ${cardProgress} `; }; +const recalculatePercentages = (languages) => { + // recalculating percentages so that, + // compact layout's progress bar does not break when hiding languages + const totalSum = languages.reduce( + (totalSum, language) => totalSum + language.percent, + 0, + ); + const weight = (100 / totalSum).toFixed(2); + languages.forEach((language) => { + language.percent = (language.percent * weight).toFixed(2); + }); +}; + const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { - const { languages } = stats; + let { languages } = stats; const { hide_title = false, hide_border = false, + hide, line_height = 25, title_color, icon_color, @@ -104,6 +122,15 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { border_color, } = options; + const shouldHideLangs = Array.isArray(hide) && hide.length > 0; + if (shouldHideLangs) { + const languagesToHide = new Set(hide.map((lang) => lowercaseTrim(lang))); + languages = languages.filter( + (lang) => !languagesToHide.has(lowercaseTrim(lang.name)), + ); + recalculatePercentages(languages); + } + const i18n = new I18n({ locale, translations: wakatimeCardLocales, @@ -131,8 +158,8 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { const filteredLanguages = languages ? languages - .filter((language) => language.hours || language.minutes) - .slice(0, langsCount) + .filter((language) => language.hours || language.minutes) + .slice(0, langsCount) : []; // Calculate the card height depending on how many items there are @@ -186,17 +213,16 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { ${compactProgressBar} ${createLanguageTextNode({ - x: 0, - y: 25, - langs: filteredLanguages, - totalSize: 100, - }).join("")} + x: 0, + y: 25, + langs: filteredLanguages, + totalSize: 100, + }).join("")} `; } else { finalLayout = flexLayout({ items: filteredLanguages.length - ? filteredLanguages - .map((language) => { + ? filteredLanguages.map((language) => { return createTextNode({ id: language.name, label: language.name, @@ -208,11 +234,11 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => { }); }) : [ - noCodingActivityNode({ - color: textColor, - text: i18n.t("wakatimecard.nocodingactivity"), - }), - ], + noCodingActivityNode({ + color: textColor, + text: i18n.t("wakatimecard.nocodingactivity"), + }), + ], gap: lheight, direction: "column", }).join(""); diff --git a/src/common/utils.js b/src/common/utils.js index 64cc75658bf1c..e9beb54b36c82 100644 --- a/src/common/utils.js +++ b/src/common/utils.js @@ -230,6 +230,7 @@ function measureText(str, fontSize = 10) { .reduce((cur, acc) => acc + cur) * fontSize ); } +const lowercaseTrim = (name) => name.toLowerCase().trim(); module.exports = { renderError, @@ -248,4 +249,5 @@ module.exports = { logger, CONSTANTS, CustomError, + lowercaseTrim, }; diff --git a/tests/__snapshots__/renderWakatimeCard.test.js.snap b/tests/__snapshots__/renderWakatimeCard.test.js.snap index c46f950c40dfe..c651c62a69ccd 100644 --- a/tests/__snapshots__/renderWakatimeCard.test.js.snap +++ b/tests/__snapshots__/renderWakatimeCard.test.js.snap @@ -99,12 +99,11 @@ exports[`Test Render Wakatime Card should render correctly 1`] = ` - Other: + Other: 19 mins @@ -122,12 +121,11 @@ exports[`Test Render Wakatime Card should render correctly 1`] = ` - TypeScript: + TypeScript: 1 min diff --git a/tests/renderTopLanguages.test.js b/tests/renderTopLanguages.test.js index 66946ce56e1c8..3591bc504a8af 100644 --- a/tests/renderTopLanguages.test.js +++ b/tests/renderTopLanguages.test.js @@ -1,6 +1,5 @@ require("@testing-library/jest-dom"); const cssToObject = require("css-to-object"); -const fetchTopLanguages = require("../src/fetchers/top-languages-fetcher"); const renderTopLanguages = require("../src/cards/top-languages-card"); const { queryByTestId, queryAllByTestId } = require("@testing-library/dom"); diff --git a/tests/renderWakatimeCard.test.js b/tests/renderWakatimeCard.test.js index 47f718cb33b07..658c52df4e9a9 100644 --- a/tests/renderWakatimeCard.test.js +++ b/tests/renderWakatimeCard.test.js @@ -1,6 +1,7 @@ require("@testing-library/jest-dom"); -const renderWakatimeCard = require("../src/cards/wakatime-card"); +const { queryByTestId } = require("@testing-library/dom"); +const renderWakatimeCard = require("../src/cards/wakatime-card"); const { wakaTimeData } = require("./fetchWakatime.test"); describe("Test Render Wakatime Card", () => { @@ -16,6 +17,16 @@ describe("Test Render Wakatime Card", () => { expect(card).toMatchSnapshot(); }); + it("should hide languages when hide is passed", () => { + document.body.innerHTML = renderWakatimeCard(wakaTimeData.data, { + hide: ["YAML", "Other"], + }); + + expect(queryByTestId(document.body, /YAML/i)).toBeNull(); + expect(queryByTestId(document.body, /Other/i)).toBeNull(); + expect(queryByTestId(document.body, /TypeScript/i)).not.toBeNull(); + }); + it("should render translations", () => { document.body.innerHTML = renderWakatimeCard({}, { locale: "cn" }); expect(document.getElementsByClassName("header")[0].textContent).toBe( @@ -28,9 +39,11 @@ describe("Test Render Wakatime Card", () => { }); it("should render without rounding", () => { - document.body.innerHTML = renderWakatimeCard(wakaTimeData.data, { border_radius: "0" }); + document.body.innerHTML = renderWakatimeCard(wakaTimeData.data, { + border_radius: "0", + }); expect(document.querySelector("rect")).toHaveAttribute("rx", "0"); - document.body.innerHTML = renderWakatimeCard(wakaTimeData.data, { }); + document.body.innerHTML = renderWakatimeCard(wakaTimeData.data, {}); expect(document.querySelector("rect")).toHaveAttribute("rx", "4.5"); }); });