Skip to content

Commit

Permalink
feat: add wakatime card (#392)
Browse files Browse the repository at this point in the history
* Adds wakatime card route

* Adds language progress on wakatime card

* Adds wakatime card on README

* Adds no coding activity node

* Remove percent displayed on wakatime's card

* Update readme

* refactor: refactored code & added tests

Co-authored-by: Anurag <[email protected]>
  • Loading branch information
willianrod and anuraghazra authored Sep 19, 2020
1 parent e377770 commit 6e73a00
Show file tree
Hide file tree
Showing 7 changed files with 586 additions and 0 deletions.
59 changes: 59 additions & 0 deletions api/wakatime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
require("dotenv").config();
const {
renderError,
parseBoolean,
clampValue,
CONSTANTS,
} = require("../src/common/utils");
const { fetchLast7Days } = require("../src/fetchers/wakatime-fetcher");
const wakatimeCard = require("../src/cards/wakatime-card");

module.exports = async (req, res) => {
const {
username,
title_color,
icon_color,
hide_border,
line_height,
text_color,
bg_color,
theme,
cache_seconds,
hide_title,
hide_progress,
} = req.query;

res.setHeader("Content-Type", "image/svg+xml");

try {
const last7Days = await fetchLast7Days({ username });

let cacheSeconds = clampValue(
parseInt(cache_seconds || CONSTANTS.TWO_HOURS, 10),
CONSTANTS.TWO_HOURS,
CONSTANTS.ONE_DAY
);

if (!cache_seconds) {
cacheSeconds = CONSTANTS.FOUR_HOURS;
}

res.setHeader("Cache-Control", `public, max-age=${cacheSeconds}`);

return res.send(
wakatimeCard(last7Days, {
hide_title: parseBoolean(hide_title),
hide_border: parseBoolean(hide_border),
line_height,
title_color,
icon_color,
text_color,
bg_color,
theme,
hide_progress,
})
);
} catch (err) {
return res.send(renderError(err.message, err.secondaryMessage));
}
};
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"dotenv": "^8.2.0",
"emoji-name-map": "^1.2.8",
"github-username-regex": "^1.0.0",
"prettier": "^2.1.2",
"word-wrap": "^1.2.3"
},
"husky": {
Expand Down
26 changes: 26 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
- [GitHub Stats Card](#github-stats-card)
- [GitHub Extra Pins](#github-extra-pins)
- [Top Languages Card](#top-languages-card)
- [Wakatime Week Stats](#wakatime-week-stats)
- [Themes](#themes)
- [Customization](#customization)
- [Deploy Yourself](#deploy-on-your-own-vercel-instance)
Expand Down Expand Up @@ -171,6 +172,13 @@ You can provide multiple comma-separated values in bg_color option to render a g
> Language names should be uri-escaped, as specified in [Percent Encoding](https://en.wikipedia.org/wiki/Percent-encoding)
> (i.e: `c++` should become `c%2B%2B`, `jupyter notebook` should become `jupyter%20notebook`, etc.)
#### Wakatime Card Exclusive Options:

- `hide_title` - _(boolean)_
- `hide_border` - _(boolean)_
- `line_height` - Sets the line-height between text _(number)_
- `hide_progress` - Hides the progress bar and percentage _(boolean)_

---

# GitHub Extra Pins
Expand Down Expand Up @@ -245,6 +253,20 @@ You can use the `&layout=compact` option to change the card design.

[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra&layout=compact)](https://github.com/anuraghazra/github-readme-stats)

# Wakatime Week Stats

Change the `?username=` value to your Wakatime username.

```md
[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)
```

### Demo

[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](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)

---

### All Demos
Expand Down Expand Up @@ -287,6 +309,10 @@ Choose from any of the [default themes](#themes)

[![Top Langs](https://github-readme-stats.vercel.app/api/top-langs/?username=anuraghazra)](https://github.com/anuraghazra/github-readme-stats)

- Wakatime card

[![willianrod's wakatime stats](https://github-readme-stats.vercel.app/api/wakatime?username=willianrod)](https://github.com/anuraghazra/github-readme-stats)

---

### Quick Tip (Align The Repo Cards)
Expand Down
156 changes: 156 additions & 0 deletions src/cards/wakatime-card.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
const { getCardColors, FlexLayout, clampValue } = require("../common/utils");
const { getStyles } = require("../getStyles");
const icons = require("../common/icons");
const Card = require("../common/Card");

const noCodingActivityNode = ({ color }) => {
return `
<text x="25" y="11" class="stat bold" fill="${color}">No coding activity this week</text>
`;
};

const createProgressNode = ({
width,
color,
progress,
progressBarBackgroundColor,
}) => {
const progressPercentage = clampValue(progress, 2, 100);

return `
<svg width="${width}" overflow="auto">
<rect rx="5" ry="5" x="110" y="4" width="${width}" height="8" fill="${progressBarBackgroundColor}"></rect>
<rect
height="8"
fill="${color}"
rx="5" ry="5" x="110" y="4"
data-testid="lang-progress"
width="${progressPercentage}%"
>
</rect>
</svg>
`;
};

const createTextNode = ({
id,
label,
value,
index,
percent,
hideProgress,
progressBarColor,
progressBarBackgroundColor,
}) => {
const staggerDelay = (index + 3) * 150;

const cardProgress = hideProgress
? null
: createProgressNode({
progress: percent,
color: progressBarColor,
width: 220,
name: label,
progressBarBackgroundColor,
});

return `
<g class="stagger" style="animation-delay: ${staggerDelay}ms" transform="translate(25, 0)">
<text class="stat bold" y="12.5">${label}:</text>
<text
class="stat"
x="${hideProgress ? 170 : 350}"
y="12.5"
data-testid="${id}"
>${value}</text>
${cardProgress}
</g>
`;
};

const renderWakatimeCard = (stats = {}, options = { hide: [] }) => {
const { languages } = stats;
const {
hide_title = false,
hide_border = false,
line_height = 25,
title_color,
icon_color,
text_color,
bg_color,
theme = "default",
hide_progress,
} = options;

const lheight = parseInt(line_height, 10);

// returns theme based colors with proper overrides and defaults
const { titleColor, textColor, iconColor, bgColor } = getCardColors({
title_color,
icon_color,
text_color,
bg_color,
theme,
});

const statItems = languages
? languages
.filter((language) => language.hours || language.minutes)
.map((language) => {
return createTextNode({
id: language.name,
label: language.name,
value: language.text,
percent: language.percent,
progressBarColor: titleColor,
progressBarBackgroundColor: textColor,
hideProgress: hide_progress,
});
})
: [];

// Calculate the card height depending on how many items there are
// but if rank circle is visible clamp the minimum height to `150`
let height = Math.max(45 + (statItems.length + 1) * lheight, 150);

const cssStyles = getStyles({
titleColor,
textColor,
iconColor,
});

const card = new Card({
title: "Wakatime week stats",
width: 495,
height,
colors: {
titleColor,
textColor,
iconColor,
bgColor,
},
});

card.setHideBorder(hide_border);
card.setHideTitle(hide_title);
card.setCSS(
`
${cssStyles}
.lang-name { font: 400 11px 'Segoe UI', Ubuntu, Sans-Serif; fill: ${textColor} }
`
);

return card.render(`
<svg x="0" y="0" width="100%">
${FlexLayout({
items: statItems.length
? statItems
: [noCodingActivityNode({ color: textColor })],
gap: lheight,
direction: "column",
}).join("")}
</svg>
`);
};

module.exports = renderWakatimeCard;
13 changes: 13 additions & 0 deletions src/fetchers/wakatime-fetcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const axios = require("axios");

const fetchLast7Days = async ({ username }) => {
const { data } = await axios.get(
`https://wakatime.com/api/v1/users/${username}/stats/last_7_days?is_including_today=true`
);

return data.data;
};

module.exports = {
fetchLast7Days,
};
Loading

0 comments on commit 6e73a00

Please sign in to comment.