fix: include icon library to fix missing emojis on some platforms (resolve #119)

This commit is contained in:
Ferdinand Mütsch 2021-04-16 17:07:11 +02:00
parent dca736752e
commit d3713017e3
12 changed files with 151 additions and 31 deletions

4
.gitignore vendored
View File

@ -8,3 +8,7 @@ build
config*.yml
!config.default.yml
pkged.go
package.json
yarn.lock
package-lock.json
node_modules

View File

@ -256,13 +256,22 @@ However, if you want to expose your wakapi instance to the public anyway, you ne
CGO_FLAGS="-g -O2 -Wno-return-local-addr" go test -json -coverprofile=coverage/coverage.out ./... -run ./...
```
### Building Tailwind
To keep things minimal, Wakapi does not contain a `package.json`, `node_modules` or any sort of frontend build step. Instead, all JS and CSS assets are included as static files and checked in to Git. This way we can avoid requiring NodeJS to build Wakapi. However, for [TailwindCSS](https://tailwindcss.com/docs/installation#building-for-production) it makes sense to run it through a "build" step to benefit from purging and significantly reduce it in size. To only require this at the time of development, the compiled asset is checked in to Git as well.
### Building web assets
To keep things minimal, Wakapi does not contain a `package.json`, `node_modules` or any sort of frontend build step. Instead, all JS and CSS assets are included as static files and checked in to Git. This way we can avoid requiring NodeJS to build Wakapi. However, for [TailwindCSS](https://tailwindcss.com/docs/installation#building-for-production) it makes sense to run it through a "build" step to benefit from purging and significantly reduce it in size. To only require this at the time of development, the compiled asset is checked in to Git as well. Similarly, [Iconify](https://iconify.design/docs/icon-bundles/) bundles are also created at development time and checked in to the repo.
#### TailwindCSS
```bash
$ tailwindcss-cli build static/assets/vendor/tailwind.css -o static/assets/vendor/tailwind.dist.css
```
#### Iconify
```bash
$ yarn add -D @iconify/json-tools @iconify/json
$ node scripts/bundle_icons.js
```
New icons can be added by editing the `icons` array in [scripts/bundle_icons.js](scripts/bundle_icons.js).
## 🙏 Support
If you like this project, please consider supporting it 🙂. You can donate either through [buying me a coffee](https://buymeacoff.ee/n1try) or becoming a GitHub sponsor. Every little donation is highly appreciated and boosts the developers' motivation to keep improving Wakapi!

80
scripts/bundle_icons.js Executable file
View File

@ -0,0 +1,80 @@
#!/usr/bin/env node
'use strict'
// Usage:
// yarn add -D @iconify/json-tools @iconify/json
// node bundle_icons.js
// https://iconify.design/docs/icon-bundles/
const fs = require('fs')
const path = require('path')
const { Collection } = require('@iconify/json-tools')
let icons = [
'fxemoji:key',
'fxemoji:rocket',
'fxemoji:satelliteantenna',
'fxemoji:lockandkey',
'fxemoji:clipboard',
'flat-color-icons:donate',
'flat-color-icons:clock',
'codicon:github-inverted',
'ant-design:check-square-filled',
'emojione-v1:white-heavy-check-mark',
'emojione-v1:alarm-clock',
'emojione-v1:warning',
'emojione-v1:backhand-index-pointing-right',
'twemoji:light-bulb',
'noto:play-button',
'noto:stop-button',
'noto:lock',
'twemoji:gear',
'eva:corner-right-down-fill',
'bi:heart-fill',
]
const output = path.normalize(path.join(__dirname, '../static/assets/icons.js'))
const pretty = false
// Sort icons by collections: filtered[prefix][array of icons]
let filtered = {}
icons.forEach(icon => {
let parts = icon.split(':'),
prefix
if (parts.length > 1) {
prefix = parts.shift()
icon = parts.join(':')
} else {
parts = icon.split('-')
prefix = parts.shift()
icon = parts.join('-')
}
if (filtered[prefix] === void 0) {
filtered[prefix] = []
}
if (filtered[prefix].indexOf(icon) === -1) {
filtered[prefix].push(icon)
}
})
// Parse each collection
let code = ''
Object.keys(filtered).forEach(prefix => {
let collection = new Collection()
if (!collection.loadIconifyCollection(prefix)) {
console.error('Error loading collection', prefix)
return
}
code += collection.scriptify({
icons: filtered[prefix],
optimize: true,
pretty: pretty
})
})
// Save code
fs.writeFileSync(output, code, 'utf8')
console.log('Saved bundle to', output, ' (' + code.length + ' bytes)')

9
static/assets/icons.js Normal file

File diff suppressed because one or more lines are too long

View File

@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><g fill="#eee"><path fill-rule="evenodd" clip-rule="evenodd" d="M64 5.103c-33.347 0-60.388 27.035-60.388 60.388 0 26.682 17.303 49.317 41.297 57.303 3.017.56 4.125-1.31 4.125-2.905 0-1.44-.056-6.197-.082-11.243-16.8 3.653-20.345-7.125-20.345-7.125-2.747-6.98-6.705-8.836-6.705-8.836-5.48-3.748.413-3.67.413-3.67 6.063.425 9.257 6.223 9.257 6.223 5.386 9.23 14.127 6.562 17.573 5.02.542-3.903 2.107-6.568 3.834-8.076-13.413-1.525-27.514-6.704-27.514-29.843 0-6.593 2.36-11.98 6.223-16.21-.628-1.52-2.695-7.662.584-15.98 0 0 5.07-1.623 16.61 6.19C53.7 35 58.867 34.327 64 34.304c5.13.023 10.3.694 15.127 2.033 11.526-7.813 16.59-6.19 16.59-6.19 3.287 8.317 1.22 14.46.593 15.98 3.872 4.23 6.215 9.617 6.215 16.21 0 23.194-14.127 28.3-27.574 29.796 2.167 1.874 4.097 5.55 4.097 11.183 0 8.08-.07 14.583-.07 16.572 0 1.607 1.088 3.49 4.148 2.897 23.98-7.994 41.263-30.622 41.263-57.294C124.388 32.14 97.35 5.104 64 5.104z"/><path d="M26.484 91.806c-.133.3-.605.39-1.035.185-.44-.196-.685-.605-.543-.906.13-.31.603-.395 1.04-.188.44.197.69.61.537.91zm-.743-.55M28.93 94.535c-.287.267-.85.143-1.232-.28-.396-.42-.47-.983-.177-1.254.298-.266.844-.14 1.24.28.394.426.472.984.17 1.255zm-.575-.618M31.312 98.012c-.37.258-.976.017-1.35-.52-.37-.538-.37-1.183.01-1.44.373-.258.97-.025 1.35.507.368.545.368 1.19-.01 1.452zm0 0M34.573 101.373c-.33.365-1.036.267-1.552-.23-.527-.487-.674-1.18-.343-1.544.336-.366 1.045-.264 1.564.23.527.486.686 1.18.333 1.543zm0 0M39.073 103.324c-.147.473-.825.688-1.51.486-.683-.207-1.13-.76-.99-1.238.14-.477.823-.7 1.512-.485.683.206 1.13.756.988 1.237zm0 0M44.016 103.685c.017.498-.563.91-1.28.92-.723.017-1.308-.387-1.315-.877 0-.503.568-.91 1.29-.924.717-.013 1.306.387 1.306.88zm0 0M48.614 102.903c.086.485-.413.984-1.126 1.117-.7.13-1.35-.172-1.44-.653-.086-.498.422-.997 1.122-1.126.714-.123 1.354.17 1.444.663zm0 0"/></g></svg>

Before

Width:  |  Height:  |  Size: 1.9 KiB

File diff suppressed because one or more lines are too long

2
static/assets/vendor/twemoji.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -1,2 +1,4 @@
<script src="assets/vendor/iconify.basic.min.js"></script>
<script src="assets/vendor/seedrandom.min.js"></script>
<script src="assets/vendor/Chart.bundle.min.js"></script>
<script src="assets/vendor/Chart.bundle.min.js"></script>
<script src="assets/icons.js"></script>

View File

@ -3,7 +3,7 @@
v{{ getVersion }} @ {{ getDbType }}
</div>
<div>
Made with &nbsp; 🤍 &nbsp; by <a href="https://muetsch.io" class="border-b border-green-700">Ferdinand Mütsch</a> as <a
Made with &nbsp; <span class="iconify inline" data-icon="bi:heart-fill"></span> &nbsp; by <a href="https://muetsch.io" class="border-b border-green-700">Ferdinand Mütsch</a> as <a
href="https://github.com/muety/wakapi" class="border-b border-green-700">open-source</a> software
</div>
<div>

View File

@ -11,21 +11,21 @@
<div class="absolute flex top-0 right-0 mr-8 mt-10 py-2">
<div class="mx-1">
<a href="login" class="py-1 px-3 h-8 block rounded border border-green-700 text-white text-sm">🔑
&nbsp;Login</a>
<a href="login" class="py-1 px-3 h-8 block rounded border border-green-700 text-white text-sm">
<span class="iconify inline" data-icon="fxemoji:key"></span> &nbsp;Login</a>
</div>
</div>
<main class="mt-10 flex-grow flex justify-center w-full">
<div class="flex flex-col text-white">
<h1 class="text-4xl font-semibold antialiased text-center mb-2">Keep Track of <span
class="text-green-700">Your</span> Coding Time 🕓</h1>
class="text-green-700">Your</span> Coding Time <span class="iconify inline" data-icon="flat-color-icons:clock"></span></h1>
<p class="text-center text-gray-500 text-xl my-2">Wakapi is an open-source tool that helps you keep track of the
time you have spent coding on different projects in different programming languages and more. Ideal for
statistics freaks and anyone else.</p>
<p class="text-center text-gray-500 text-xl my-4">
<span class="mr-1">💡 The system has tracked a total of </span>
<span class="mr-1"><span class="iconify inline" data-icon="twemoji:light-bulb"></span> The system has tracked a total of </span>
{{ range $d := .TotalHours | printf "%d" | toRunes }}
<span class="bg-gray-900 rounded-sm p-1 border border-gray-700 font-mono" style="margin: auto -2px;" title="{{ $.TotalHours }} hours (updated every hour)">{{ $d }}</span>
{{ end }}
@ -39,20 +39,20 @@
<div class="flex justify-center mt-4 mb-8 space-x-2">
<a href="login">
<button type="button"
class="py-1 px-3 rounded bg-green-700 hover:bg-green-800 text-white font-semibold">🚀 Try it!
class="py-1 px-3 rounded bg-green-700 hover:bg-green-800 text-white font-semibold"><span class="iconify inline" data-icon="fxemoji:rocket"></span> Try it!
</button>
</a>
<a href="https://github.com/muety/wakapi#%EF%B8%8F-how-to-use" target="_blank" rel="noopener noreferrer">
<button type="button" class="py-1 px-3 h-8 rounded border border-green-700 text-white">📡 Host it
<button type="button" class="py-1 px-3 h-8 rounded border border-green-700 text-white"><span class="iconify inline" data-icon="fxemoji:satelliteantenna"></span> Host it
</button>
</a>
<a href="https://liberapay.com/muety" target="_blank" rel="noopener noreferrer">
<button type="button" class="py-1 px-3 h-8 rounded border border-green-700 text-white">🙏 Support it
<button type="button" class="py-1 px-3 h-8 rounded border border-green-700 text-white"><span class="iconify inline" data-icon="flat-color-icons:donate"></span> Support it
</button>
</a>
<a href="https://github.com/muety/wakapi" target="_blank" rel="noopener noreferrer">
<button type="button" class="py-1 px-3 h-8 rounded border border-green-700 text-white">
<img alt="GitHub Icon" src="assets/images/ghicon.svg" width="22px">
<span class="iconify inline text-white" data-icon="codicon:github-inverted"></span>
</button>
</a>
</div>
@ -65,19 +65,19 @@
<h1 class="font-semibold text-xl text-white m-0 border-b-4 border-green-700">Features</h1>
<div class="mt-4 text-lg">
<ul>
<li> &nbsp; 100 % free and open-source</li>
<li> &nbsp; Built by developers for developers</li>
<li> &nbsp; Fancy statistics and plots</li>
<li> &nbsp; Cool badges for readmes</li>
<li> &nbsp; Intuitive REST API</li>
<li> &nbsp; Compatible with <a href="https://wakatime.com" target="_blank"
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; 100 % free and open-source</li>
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; Built by developers for developers</li>
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; Fancy statistics and plots</li>
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; Cool badges for readmes</li>
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; Intuitive REST API</li>
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; Compatible with <a href="https://wakatime.com" target="_blank"
rel="noopener noreferrer" class="underline">Wakatime</a></li>
<li> &nbsp; <a href="https://prometheus.io" target="_blank" rel="noopener noreferrer"
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; <a href="https://prometheus.io" target="_blank" rel="noopener noreferrer"
class="underline">Prometheus</a> metrics via <a
href="https://github.com/MacroPower/wakatime_exporter" target="_blank"
rel="noopener noreferrer" class="underline">exporter</a></li>
<li> &nbsp; Lightning fast</li>
<li> &nbsp; Self-hosted</li>
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; Lightning fast</li>
<li><span class="iconify inline text-green-700" data-icon="ant-design:check-square-filled"></span> &nbsp; Self-hosted</li>
</ul>
</div>
</div>

View File

@ -383,7 +383,7 @@
<div class="flex justify-end">
<button id="btn-import-wakatime" type="button" style="width: 130px"
class="py-1 px-3 my-3 rounded bg-green-700 hover:bg-green-800 text-white text-sm">
Import Data
<span class="iconify inline" data-icon="eva:corner-right-down-fill"></span> Import Data
</button>
</div>
{{ end }}
@ -394,7 +394,7 @@
</form>
<p class="mt-6">
<span class="font-semibold">👉 Please note:</span>
<span class="font-semibold"><span class="iconify inline" data-icon="emojione-v1:backhand-index-pointing-right"></span> Please note:</span>
<span>When enabling this feature, the operators of this server will, in theory (!), have unlimited access to your data stored in WakaTime. If you are concerned about your privacy, please do not enable this integration or wait for OAuth 2 authentication (<a
class="underline" target="_blank" href="https://github.com/muety/wakapi/issues/94"
rel="noopener noreferrer">#94</a>) to be implemented.</span>
@ -474,7 +474,7 @@
<details class="mb-8 pb-8">
<summary class="cursor-pointer">
<h2 class="font-semibold text-lg text-white m-0 border-b-2 border-green-700 inline-block" id="danger">
⚠️ Danger Zone
<span class="iconify inline" data-icon="emojione-v1:warning"></span>&nbsp; Danger Zone
</h2>
</summary>
<div class="w-full">

View File

@ -15,18 +15,20 @@
value="{{ .ApiKey }}" style="min-width: 330px">
</div>
<div class="flex items-center px-2 border-l border-gray-700">
<button title="Copy to clipboard" onclick="copyApiKey(event)">📋</button>
<button title="Copy to clipboard" onclick="copyApiKey(event)"><span class="iconify inline" data-icon="fxemoji:clipboard"></span></button>
</div>
</div>
<div class="absolute flex top-0 right-0 mr-8 mt-10 py-2">
<div class="mx-1">
<button type="button" class="py-1 px-3 h-8 rounded border border-green-700 text-white text-sm"
onclick="showApiKeyPopup(event)">🔐
onclick="showApiKeyPopup(event)"><span class="iconify inline" data-icon="fxemoji:lockandkey"></span>
</button>
</div>
<div class="mx-1">
<a href="settings" class="py-1 px-3 h-8 block rounded border border-green-700 text-white text-sm">⚙️</a>
<a href="settings" class="py-1 px-3 h-8 block rounded border border-green-700 text-white text-sm">
<span class="iconify inline" data-icon="twemoji:gear"></span>
</a>
</div>
<div class="mx-1">
<form action="logout" method="post">
@ -44,12 +46,12 @@
<div class="self-center border border-gray-700 shadow mt-8 rounded-md p-4 bg-gray-900">
<form class="text-white flex flex-nowrap items-center justify-center self-center max-w-xl flex-wrap space-x-8">
<div class="flex space-x-1">
<label for="from-date-picker" class="text-gray-300 pl-1">▶️ Start:</label>
<label for="from-date-picker" class="text-gray-300 pl-1"><span class="iconify inline" data-icon="noto:play-button"></span> Start:</label>
<input id="from-date-picker" type="date" name="from" max="{{ .ToTime.T | simpledate }}" class="text-sm text-gray-300 bg-gray-800 rounded-md text-center cursor-pointer"
value="{{ .From | simpledate }}" required>
</div>
<div class="flex space-x-1">
<label for="to-date-picker" class="text-gray-300 pl-1">⏹️ End:</label>
<label for="to-date-picker" class="text-gray-300 pl-1"><span class="iconify inline" data-icon="noto:stop-button"></span> End:</label>
<input id="to-date-picker" type="date" name="to" min="{{ .FromTime.T | simpledate }}" class="text-sm text-gray-300 bg-gray-800 rounded-md text-center cursor-pointer"
value="{{ .To | ceildate | simpledate }}" required>
</div>
@ -80,7 +82,7 @@
{{ if .User.HasData }}
<span class="text-white text-lg text-gray-300 text-center mb-4">
<span class="text-xl">&nbsp;</span>
<span class="text-xl"><span class="iconify inline" data-icon="emojione-v1:alarm-clock"></span>&nbsp;</span>
Showing a total of <span id="total-span" title="Total Hours" class="text-white text-xl font-semibold border-b-2 border-green-700"></span>
<span class="text-sm my-2">
(from <span title="Start Time" class="border-b border-gray-700">{{ .FromTime.T | date }}</span> to <span title="End Time" class="border-b border-gray-700">{{ .ToTime.T | date }}</span>)