Skip to content

Commit d4126ba

Browse files
authored
🔀 Merge pull request #1278 from wozboz/master
Add new widget for RescueTime
2 parents 31f3b2b + c45e058 commit d4126ba

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed

docs/widgets.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
3939
- [Mvg Departure](#mvg-departure)
4040
- [Mvg Connection](#mvg-connection)
4141
- [Custom search](#custom-search)
42+
- [Rescuetime overview](#rescuetime-overview)
4243
- **[Self-Hosted Services Widgets](#self-hosted-services-widgets)**
4344
- [System Info](#system-info)
4445
- [Cron Monitoring](#cron-monitoring-health-checks)
@@ -1339,6 +1340,38 @@ This widget allows searching multiple search engines from dashy.
13391340

13401341
---
13411342

1343+
### RescueTime Overview
1344+
1345+
Show an overview of how you have spent your time for the current day.
1346+
1347+
<p align="center"><img width="400" src="https://i.ibb.co/bvx3PQM/rescuetime.png" /></p>
1348+
1349+
#### Options
1350+
1351+
**Field** | **Type** | **Required** | **Description**
1352+
--- | --- | --- | ---
1353+
**`apiKey`** | `string` | required | The API-Key generated in the RescueTime UI.
1354+
1355+
1356+
#### Example
1357+
1358+
```yaml
1359+
- type: rescue-time
1360+
useProxy: true
1361+
options:
1362+
apiKey: abcdefghijkl_mnop
1363+
```
1364+
#### Info
1365+
1366+
- **CORS**: 🟢 Required
1367+
- **Auth**: 🔴 Required
1368+
- **Price**: 🟠 Depends on user subscription
1369+
- **Host**: [RescueTime](https://www.rescuetime.com)
1370+
- **Privacy**: _See [RescueTime Privacy](https://www.rescuetime.com/privacy)_
1371+
1372+
---
1373+
1374+
13421375

13431376
## Self-Hosted Services Widgets
13441377

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<template>
2+
<div class="rescuetime-wrapper">
3+
<div class="title-row">
4+
<p class="title-rank">Rank</p>
5+
<p class="title-name">Category</p>
6+
<p class="title-time">Time spent</p>
7+
</div>
8+
<div
9+
v-for="(category, indx) in categories"
10+
:key="indx"
11+
class="category-row"
12+
>
13+
<p class="category-rank">{{ category.rank }}</p>
14+
<p class="category-name">{{ indx }}</p>
15+
<p class="category-time">{{ category.minutes }} min</p>
16+
</div>
17+
</div>
18+
</template>
19+
<script>
20+
21+
import WidgetMixin from '@/mixins/WidgetMixin';
22+
import { widgetApiEndpoints } from '@/utils/defaults';
23+
24+
export default {
25+
mixins: [WidgetMixin],
26+
data() {
27+
return {
28+
categories: [],
29+
};
30+
},
31+
mounted() {
32+
this.checkOptions();
33+
},
34+
computed: {
35+
endpoint() {
36+
const todaystring = this.getDate();
37+
return `${widgetApiEndpoints.rescueTime}?key=${this.options.apiKey}&restrict_begin=${todaystring}&restrict_end=${todaystring}&restrict_kind=overview&format=json`;
38+
},
39+
},
40+
methods: {
41+
fetchData() {
42+
this.makeRequest(this.endpoint).then(this.processData);
43+
},
44+
processData(data) {
45+
const formateddata = this.calculateTimeCategories(data);
46+
this.categories = formateddata;
47+
},
48+
checkOptions() {
49+
const ops = this.options;
50+
if (!ops.apiKey) this.error('Missing API key for RescueTime');
51+
},
52+
getDate() {
53+
const today = new Date();
54+
let day = today.getDate();
55+
let month = today.getMonth() + 1;
56+
const year = today.getFullYear();
57+
if (day < 10) {
58+
day = `0${day}`;
59+
}
60+
if (month < 10) {
61+
month = `0${month}`;
62+
}
63+
return `${day}-${month}-${year}`;
64+
},
65+
calculateTimeCategories(timeArray) {
66+
const results = {};
67+
for (let i = 0; i < timeArray.rows.length; i += 1) {
68+
const [rank, seconds, persons, category] = timeArray.rows[i];
69+
const minutes = (parseInt(seconds, 10) / 60).toFixed(2);
70+
results[category] = { minutes, rank, persons };
71+
}
72+
return results;
73+
},
74+
},
75+
};
76+
77+
</script>
78+
79+
<style scoped lang="scss">
80+
.rescuetime-wrapper {
81+
padding: 0.5rem 0;
82+
.title-row {
83+
display: flex;
84+
justify-content: space-between;
85+
p {
86+
margin: 0.25rem 0;
87+
color: var(--widget-text-color);
88+
font-weight: 700;
89+
font-size: 1.15rem;
90+
}
91+
&:not(:last-child) {
92+
border-bottom: 1px dashed var(--widget-text-color);
93+
}
94+
}
95+
.category-rank {
96+
font-weight: 700;
97+
}
98+
.category-row {
99+
display: flex;
100+
justify-content: space-between;
101+
p {
102+
margin: 0.25rem 0;
103+
color: var(--widget-text-color);
104+
opacity: var(--dimming-factor);
105+
}
106+
}
107+
}
108+
109+
</style>

src/components/Widgets/WidgetBase.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ const COMPAT = {
104104
'proxmox-lists': 'Proxmox',
105105
'public-holidays': 'PublicHolidays',
106106
'public-ip': 'PublicIp',
107+
'rescue-time': 'RescueTime',
107108
'rss-feed': 'RssFeed',
108109
sabnzbd: 'Sabnzbd',
109110
'sports-scores': 'SportsScores',

src/utils/defaults.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ module.exports = {
238238
publicIp2: 'https://api.ipgeolocation.io/ipgeo',
239239
publicIp3: 'http://ip-api.com/json',
240240
readMeStats: 'https://github-readme-stats.vercel.app/api',
241+
rescueTime: 'https://www.rescuetime.com/anapi/data',
241242
rssToJson: 'https://api.rss2json.com/v1/api.json',
242243
sportsScores: 'https://www.thesportsdb.com/api/v1/json',
243244
stockPriceChart: 'https://www.alphavantage.co/query',

0 commit comments

Comments
 (0)