Compare commits

..
Author SHA1 Message Date
rickstaa 98fcc65113 refactor: remove WakaTime range loop 2023-05-09 13:44:08 +02:00
Rick Staa 65fa81f56a test: fix WakaTime tests 2023-05-08 21:47:30 +02:00
Rick Staa d80d7668b6 fix: improve WakaTime range order 2023-05-08 21:45:27 +02:00
Rick Staa 7ea55d05ad fix: fix chinese simplified translations 2023-05-08 21:40:58 +02:00
rickstaa 6b8e06b2e4 fix: Make WakaTime card compatible with new API
This commit makes sure that the WakaTime card works with the new
WakaTime API. See https://github.com/anuraghazra/github-readme-stats/issues/2698
for more information.
2023-05-08 09:04:51 +02:00
Rick Staa 688f4e4975 docs: update wakatime user (#2697)
The old example user doesn't have a WakaTime account anymore.
2023-05-06 15:29:11 +05:30
Rongrong 0caa4c5fd8 test: fix mistaken pageInfo.endCursor keys (#2657)
The previous mock logic was too simplistic and has been fixed in the
commit. If the mock logic had been properly implemented, then the
mistaken pageInfo.endCursor keys should have made the test case "should
fetch two pages of stars if 'FETCH_MULTI_PAGE_STARS' env variable is set
to `true`" stuck.
2023-05-06 08:07:03 +00:00
Alexandr Garbuzov 0c2fe4e07b Cover with test changes in #2662 pull request (#2673) 2023-05-06 07:43:37 +00:00
Fabiano CoutoandRick Staa a340900e8a fix(wakatime-fetcher): add default range to prevent user not found error (#2670)
* feat(theme): add github_dark_dimmed theme

* feat(theme): change github_dark_dimmed icon color

* contrast ratio adjustment

contrast ratio adjustment on github_dark_dimmed theme

* feat(theme): readme preview

* feat(theme): github themes next to each other

* github themes next to each other

* feat(RankIcon): add rank icon option

* feat(RankIcon): extract rankIcon to icons file

* feat(RankIcon): update readme

* feat(RankIcon): test coverage

* Update readme.md

Co-authored-by: Rick Staa <rick.staa@outlook.com>

* add wakatime default range

* update wakatime demos in readme with most active user

* update wakatime demo in readme

* remove &range=all_time from wakatime demos in readme

---------

Co-authored-by: Rick Staa <rick.staa@outlook.com>
2023-05-05 23:12:28 +02:00
dependabot[bot]anddependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> 2619c12638 build(deps): bump yaml from 2.1.3 to 2.2.2 (#2644)
Bumps [yaml](https://github.com/eemeli/yaml) from 2.1.3 to 2.2.2.
- [Release notes](https://github.com/eemeli/yaml/releases)
- [Commits](https://github.com/eemeli/yaml/compare/v2.1.3...v2.2.2)

---
updated-dependencies:
- dependency-name: yaml
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-05-05 14:10:17 +00:00
Alexandr Garbuzov d306bec73e Add PRs cache cleaning workflow (#2661) 2023-05-05 14:09:23 +00:00
Alexandr Garbuzov c656f3df6b Update codecov action version to resolve github action deprecation warning (#2677) 2023-05-05 14:07:37 +00:00
Alexandr Garbuzov c6dab8b0f2 Fixed docstring for stats card create text node function to resolve type errors (#2689) 2023-05-05 14:07:15 +00:00
Alexandr Garbuzov 311204f4f9 Fixed docstring for several wakatime card gen functions to resolve multiple type errors (#2690) 2023-05-05 14:06:52 +00:00
Alexandr Garbuzov 0dc3531666 Fixed wakatime create text node func docstring to resolve vscode type errors (#2678) 2023-05-04 09:13:47 +02:00
Alexandr Garbuzov a4d6fe104f Fixed card constructor docstring to resolve vscode type errors (#2674) 2023-05-03 07:04:33 +02:00
Alexandr Garbuzov cb99414d3d Show no activity error in compact layout of wakatime card (#2662) 2023-05-01 08:21:29 +02:00
Alexandr Garbuzov 2f4279e738 Fixed vscode type error in get card colors function (#2660) 2023-04-30 08:20:26 +02:00
Rick Staa 3bd6519d39 docs: fix README language card usage order (#2659) 2023-04-29 08:25:37 +05:30
16 changed files with 212 additions and 68 deletions
+33
View File
@@ -0,0 +1,33 @@
name: prs cache clean
on:
pull_request:
types:
- closed
jobs:
cleanup:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cleanup
run: |
gh extension install actions/gh-actions-cache
REPO=${{ github.repository }}
BRANCH="refs/pull/${{ github.event.pull_request.number }}/merge"
echo "Fetching list of cache key"
cacheKeysForPR=$(gh actions-cache list -R $REPO -B $BRANCH | cut -f 1 )
## Setting this to not fail the workflow while deleting cache keys.
set +e
echo "Deleting caches..."
for cacheKey in $cacheKeysForPR
do
gh actions-cache delete $cacheKey -R $REPO -B $BRANCH --confirm
done
echo "Done"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1 -1
View File
@@ -34,4 +34,4 @@ jobs:
npm run format:check
- name: Code Coverage
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
+1 -2
View File
@@ -28,7 +28,6 @@ export default async (req, res) => {
langs_count,
hide,
api_domain,
range,
border_radius,
border_color,
} = req.query;
@@ -40,7 +39,7 @@ export default async (req, res) => {
}
try {
const stats = await fetchWakatimeStats({ username, api_domain, range });
const stats = await fetchWakatimeStats({ username, api_domain });
let cacheSeconds = clampValue(
parseInt(cache_seconds || CONSTANTS.FOUR_HOURS, 10),
+6 -6
View File
@@ -5581,9 +5581,9 @@
"dev": true
},
"node_modules/yaml": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
"integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
"integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
"dev": true,
"engines": {
"node": ">= 14"
@@ -9855,9 +9855,9 @@
"dev": true
},
"yaml": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.1.3.tgz",
"integrity": "sha512-AacA8nRULjKMX2DvWvOAdBZMOfQlypSFkjcOcu9FalllIDJ1kvlREzcdIZmidQUqqeMv7jorHjq2HlLv/+c2lg==",
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.2.2.tgz",
"integrity": "sha512-CBKFWExMn46Foo4cldiChEzn7S7SRV+wqiluAb6xmueD/fGyRHIhX8m14vVGgeFWjN540nKCNVj6P21eQjgTuA==",
"dev": true
},
"yargs": {
+8 -9
View File
@@ -328,7 +328,6 @@ You can provide multiple comma-separated values in the bg_color option to render
- `layout` - Switch between two available layouts `default` & `compact`. Default `default`.
- `langs_count` - Limit the number of languages on the card, defaults to all reported languages _(number)_.
- `api_domain` - Set a custom API domain for the card, e.g. to use services like [Hakatime](https://github.com/mujx/hakatime) or [Wakapi](https://github.com/muety/wakapi) _(string)_. Default `Waka API`.
- `range` Request a range different from your WakaTime default, e.g. `last_7_days`. See [WakaTime API docs](https://wakatime.com/developers#stats) for a list of available options. _(YYYY-MM, last_7_days, last_30_days, last_6_months, last_year, or all_time)_. Default `all_time`.
* * *
@@ -445,24 +444,24 @@ You can use the `&hide_progress=true` option to hide the percentages and the pro
# Wakatime Week Stats
> **Warning**
> Please be aware that we currently only show data from Wakatime profiles that are public. You therefore have to make sure that **BOTH** `Display code time publicly` and `Display languages, editors, os, categories publicly` are enabled.
Change the `?username=` value to your [Wakatime](https://wakatime.com) username.
```md
[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
```
> **Note**:
> Please be aware that we currently only show data from Wakatime profiles that are public.
### Demo
[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&hide_progress=true)](https://github.com/anuraghazra/github-readme-stats)
- Compact layout
[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok&layout=compact)](https://github.com/anuraghazra/github-readme-stats)
* * *
@@ -520,7 +519,7 @@ Choose from any of the [default themes](#themes)
- WakaTime card
[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
[![Harlok's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=Harlok)](https://github.com/anuraghazra/github-readme-stats)
* * *
+4 -2
View File
@@ -20,14 +20,16 @@ const RANK_CARD_DEFAULT_WIDTH = 450;
/**
* Create a stats card text item.
*
* @param {object[]} createTextNodeParams Object that contains the createTextNode parameters.
* @param {object} createTextNodeParams Object that contains the createTextNode parameters.
* @param {string} createTextNodeParams.icon The icon to display.
* @param {string} createTextNodeParams.label The label to display.
* @param {string} createTextNodeParams.value The value to display.
* @param {number} createTextNodeParams.value The value to display.
* @param {string} createTextNodeParams.id The id of the stat.
* @param {number} createTextNodeParams.index The index of the stat.
* @param {boolean} createTextNodeParams.showIcons Whether to show icons.
* @param {number} createTextNodeParams.shiftValuePos Number of pixels the value has to be shifted to the right.
* @param {boolean} createTextNodeParams.bold Whether to bold the label.
* @param {string} createTextNodeParams.number_format The format of numbers on card.
* @returns
*/
const createTextNode = ({
+54 -26
View File
@@ -36,11 +36,11 @@ const noCodingActivityNode = ({ color, text }) => {
/**
* Create compact WakaTime layout.
*
* @param {Object[]} args The function arguments.
* @param {import("../fetchers/types").WakaTimeLang[]} languages The languages array.
* @param {number} totalSize The total size of the languages.
* @param {number} x The x position of the language node.
* @param {number} y The y position of the language node.
* @param {Object} args The function arguments.
* @param {import("../fetchers/types").WakaTimeLang} args.lang The languages array.
* @param {number} args.totalSize The total size of the languages.
* @param {number} args.x The x position of the language node.
* @param {number} args.y The y position of the language node.
*/
const createCompactLangNode = ({ lang, totalSize, x, y }) => {
const color = languageColors[lang.name] || "#858585";
@@ -58,11 +58,11 @@ const createCompactLangNode = ({ lang, totalSize, x, y }) => {
/**
* Create WakaTime language text node item.
*
* @param {Object[]} args The function arguments.
* @param {import("../fetchers/types").WakaTimeLang} lang The language object.
* @param {number} totalSize The total size of the languages.
* @param {number} x The x position of the language node.
* @param {number} y The y position of the language node.
* @param {Object} args The function arguments.
* @param {import("../fetchers/types").WakaTimeLang[]} args.langs The language objects.
* @param {number} args.totalSize The total size of the languages.
* @param {number} args.x The x position of the language node.
* @param {number} args.y The y position of the language node.
*/
const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
return langs.map((lang, index) => {
@@ -86,14 +86,15 @@ const createLanguageTextNode = ({ langs, totalSize, x, y }) => {
/**
* Create WakaTime text item.
*
* @param {Object[]} args The function arguments.
* @param {string} id The id of the text node item.
* @param {string} label The label of the text node item.
* @param {string} value The value of the text node item.
* @param {number} index The index of the text node item.
* @param {percent} percent Percentage of the text node item.
* @param {boolean} hideProgress Whether to hide the progress bar.
* @param {string} progressBarBackgroundColor The color of the progress bar background.
* @param {Object} args The function arguments.
* @param {string} args.id The id of the text node item.
* @param {string} args.label The label of the text node item.
* @param {string} args.value The value of the text node item.
* @param {number} args.index The index of the text node item.
* @param {string} args.percent Percentage of the text node item.
* @param {boolean} args.hideProgress Whether to hide the progress bar.
* @param {string} args.progressBarColor The color of the progress bar.
* @param {string} args.progressBarBackgroundColor The color of the progress bar background.
*/
const createTextNode = ({
id,
@@ -267,12 +268,24 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
<rect x="25" y="0" width="${width - 50}" height="8" fill="white" rx="5" />
</mask>
${compactProgressBar}
${createLanguageTextNode({
x: 0,
y: 25,
langs: filteredLanguages,
totalSize: 100,
}).join("")}
${
filteredLanguages.length
? createLanguageTextNode({
x: 0,
y: 25,
langs: filteredLanguages,
totalSize: 100,
}).join("")
: noCodingActivityNode({
// @ts-ignore
color: textColor,
text: !stats.is_coding_activity_visible
? i18n.t("wakatimecard.notpublic")
: stats.is_other_usage_visible
? i18n.t("wakatimecard.nocodingactivity")
: i18n.t("wakatimecard.nocodedetails"),
})
}
`;
} else {
finalLayout = flexLayout({
@@ -295,7 +308,11 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
noCodingActivityNode({
// @ts-ignore
color: textColor,
text: i18n.t("wakatimecard.nocodingactivity"),
text: !stats.is_coding_activity_visible
? i18n.t("wakatimecard.notpublic")
: stats.is_other_usage_visible
? i18n.t("wakatimecard.nocodingactivity")
: i18n.t("wakatimecard.nocodedetails"),
}),
],
gap: lheight,
@@ -303,9 +320,20 @@ const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
}).join("");
}
// Get title range text
let titleText = i18n.t("wakatimecard.title");
switch (stats.range) {
case "last_7_days":
titleText += ` (${i18n.t("wakatimecard.last7days")})`;
break;
case "last_year":
titleText += ` (${i18n.t("wakatimecard.lastyear")})`;
break;
}
const card = new Card({
customTitle: custom_title,
defaultTitle: i18n.t("wakatimecard.title"),
defaultTitle: titleText,
width: 495,
height,
border_radius,
+6
View File
@@ -12,6 +12,12 @@ class Card {
* @param {string?=} args.customTitle Card custom title.
* @param {string?=} args.defaultTitle Card default title.
* @param {string?=} args.titlePrefixIcon Card title prefix icon.
* @param {object?=} args.colors Card colors arguments.
* @param {string} args.colors.titleColor Card title color.
* @param {string} args.colors.textColor Card text color.
* @param {string} args.colors.iconColor Card icon color.
* @param {string|Array} args.colors.bgColor Card background color.
* @param {string} args.colors.borderColor Card border color.
* @returns {Card} Card instance.
*/
constructor({
+2 -2
View File
@@ -194,15 +194,15 @@ const flexLayout = ({ items, gap, direction, sizes = [] }) => {
/**
* Returns theme based colors with proper overrides and defaults.
*
* @param {Object[]} args Function arguments.
* @param {Object} args Function arguments.
* @param {string} args.title_color Card title color.
* @param {string} args.text_color Card text color.
* @param {string} args.icon_color Card icon color.
* @param {string} args.bg_color Card background color.
* @param {string} args.border_color Card border color.
* @param {string} args.ring_color Card ring color.
* @param {string} args.theme Card theme.
* @param {string} args.fallbackTheme Fallback theme.
*
*/
const getCardColors = ({
title_color,
+14 -7
View File
@@ -4,25 +4,32 @@ import { MissingParamError } from "../common/utils.js";
/**
* WakaTime data fetcher.
*
* @param {{username: string, api_domain: string, range: string}} props Fetcher props.
* @returns {Promise<WakaTimeData>} WakaTime data response.
* @param {{username: string, api_domain: string}} props Fetcher props.
* @returns {Promise<wakaTimeStatsRangeData>} WakaTime data response.
*/
const fetchWakatimeStats = async ({ username, api_domain, range }) => {
const fetchWakatimeStats = async ({ username, api_domain }) => {
if (!username) throw new MissingParamError(["username"]);
// Retrieve user range.
const { data: userdata } = await axios.get(
`https://${
api_domain ? api_domain.replace(/\/$/gi, "") : "wakatime.com"
}/api/v1/users/${username}/stats`,
);
const range = userdata.data.range;
// Loop through available ranges to get user data.
try {
const { data } = await axios.get(
`https://${
api_domain ? api_domain.replace(/\/$/gi, "") : "wakatime.com"
}/api/v1/users/${username}/stats/${range || ""}?is_including_today=true`,
}/api/v1/users/${username}/stats/${range}?is_including_today=true`,
);
return data.data;
} catch (err) {
if (err.response.status < 200 || err.response.status > 299) {
throw new Error(
"Wakatime user not found, make sure you have a wakatime profile",
);
throw new Error(i18n.t("wakatimecard.nouser"));
}
throw err;
}
+20
View File
@@ -326,6 +326,26 @@ const wakatimeCardLocales = {
vi: "Thống Kê Wakatime",
se: "Wakatime statistik",
},
"wakatimecard.lastyear": {
en: "last year",
cn: "去年",
},
"wakatimecard.last7days": {
en: "last 7 days",
cn: "最近 7 天",
},
"wakatimecard.nouser": {
en: "Wakatime user not found, make sure you have a Wakatime profile",
cn: "未找到 Wakatime 用户,请确保您拥有 Wakatime 个人资料",
},
"wakatimecard.notpublic": {
en: "Wakatime user profile not public",
cn: "Wakatime 用户个人资料未公开",
},
"wakatimecard.nocodedetails": {
en: "User doesn't publicly share detailed code statistics",
cn: "用户不公开分享详细的代码统计信息",
},
"wakatimecard.nocodingactivity": {
ar: "لا يوجد نشاط برمجي لهذا الأسبوع",
cn: "本周没有编程活动",
@@ -123,7 +123,7 @@ exports[`Test Render Wakatime Card should render correctly with compact layout 1
y="0"
class="header"
data-testid="header"
>Wakatime Stats</text>
>Wakatime Stats (last 7 days)</text>
</g>
</g>
@@ -303,7 +303,7 @@ exports[`Test Render Wakatime Card should render correctly with compact layout w
y="0"
class="header"
data-testid="header"
>Wakatime Stats</text>
>Wakatime Stats (last 7 days)</text>
</g>
</g>
+1 -1
View File
@@ -43,7 +43,7 @@ const data_stats = {
nodes: [{ stargazers: { totalCount: 100 } }],
pageInfo: {
hasNextPage: false,
cursor: "cursor",
endCursor: "cursor",
},
},
},
+9 -8
View File
@@ -27,7 +27,7 @@ const data_stats = {
],
pageInfo: {
hasNextPage: true,
cursor: "cursor",
endCursor: "cursor",
},
},
},
@@ -44,7 +44,7 @@ const data_repo = {
],
pageInfo: {
hasNextPage: false,
cursor: "cursor",
endCursor: "cursor",
},
},
},
@@ -64,7 +64,7 @@ const data_repo_zero_stars = {
],
pageInfo: {
hasNextPage: true,
cursor: "cursor",
endCursor: "cursor",
},
},
},
@@ -86,11 +86,12 @@ const mock = new MockAdapter(axios);
beforeEach(() => {
process.env.FETCH_MULTI_PAGE_STARS = "false"; // Set to `false` to fetch only one page of stars.
mock
.onPost("https://api.github.com/graphql")
.replyOnce(200, data_stats)
.onPost("https://api.github.com/graphql")
.replyOnce(200, data_repo);
mock.onPost("https://api.github.com/graphql").reply((cfg) => {
return [
200,
cfg.data.includes("contributionsCollection") ? data_stats : data_repo,
];
});
});
afterEach(() => {
+35 -1
View File
@@ -8,6 +8,37 @@ afterEach(() => {
mock.reset();
});
const wakaTimeUserData = {
data: {
id: "aa437823-82d1-4b37-9b84-ab4ed89c8688",
user_id: "c7e2e900-858b-400e-bc1c-016345cf59b6",
range: "all_time",
timeout: 15,
writes_only: false,
holidays: 134,
status: "ok",
is_up_to_date: true,
days_minus_holidays: 231,
days_including_holidays: 365,
percent_calculated: 100,
human_readable_total: "691 hrs 5 mins",
is_already_updating: false,
is_stuck: false,
total_seconds_including_other_language: 2508467.924346,
is_up_to_date_pending_future: false,
total_seconds: 2487938.453846,
human_readable_daily_average: "2 hrs 59 mins",
human_readable_total_including_other_language: "696 hrs 47 mins",
daily_average_including_other_language: 10859.0,
daily_average: 10770.0,
human_readable_daily_average_including_other_language: "3 hrs",
username: "rickstaa",
is_including_today: false,
human_readable_range: "last year",
is_coding_activity_visible: true,
is_other_usage_visible: false,
},
};
const wakaTimeData = {
data: {
categories: [
@@ -103,9 +134,12 @@ const wakaTimeData = {
describe("Wakatime fetcher", () => {
it("should fetch correct wakatime data", async () => {
const username = "anuraghazra";
mock
.onGet(`https://wakatime.com/api/v1/users/${username}/stats`)
.reply(200, wakaTimeUserData);
mock
.onGet(
`https://wakatime.com/api/v1/users/${username}/stats/?is_including_today=true`,
`https://wakatime.com/api/v1/users/${username}/stats/all_time?is_including_today=true`,
)
.reply(200, wakaTimeData);
+16 -1
View File
@@ -43,7 +43,7 @@ describe("Test Render Wakatime Card", () => {
expect(
document.querySelector('g[transform="translate(0, 0)"]>text.stat.bold')
.textContent,
).toBe("本周没有编程活动");
).toBe("Wakatime 用户个人资料未公开");
});
it("should render without rounding", () => {
@@ -67,4 +67,19 @@ describe("Test Render Wakatime Card", () => {
"No coding activity this week",
);
});
it('should show "no coding activity this week" message when using compact layout and there has not been activity', () => {
document.body.innerHTML = renderWakatimeCard(
{
...wakaTimeData.data,
languages: undefined,
},
{
layout: "compact",
},
);
expect(document.querySelector(".stat").textContent).toBe(
"No coding activity this week",
);
});
});