Skip to content

Commit 0ef8936

Browse files
committed
feat: started working on category colors
1 parent 6a4072b commit 0ef8936

4 files changed

Lines changed: 84 additions & 4 deletions

File tree

src/components/CategoryEditTree.vue

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ div
88
span(v-else style="opacity: 0.6")
99
icon(name="circle" scale="0.4" style="margin-left: 1em; margin-right: 1.22em;")
1010
| {{ _class.name.slice(depth).join(" ➤ ")}}
11+
icon.ml-1(v-if="_class.data && _class.data.color" name="circle" :style="'color: ' + _class.data.color")
1112
span.ml-1(v-if="_class.children.length > 0" style="opacity: 0.5") ({{totalChildren}})
1213

1314
div.col-4.col-md-8
@@ -44,6 +45,25 @@ div
4445

4546
hr
4647

48+
div.my-1
49+
b Color
50+
51+
b-form-checkbox(v-model="editing.inherit_color" switch)
52+
| Inherit parent color
53+
b-input-group.my-1(prepend="Color" v-if="!editing.inherit_color")
54+
b-form-input(v-model="editing.color", placeholder="#FF0")
55+
icon.mt-1.ml-2(name="circle" scale="1.8" :style="{'color': editing.color}")
56+
b-btn.px-1(@click="randomColor()" style="border: 0" variant="outline-dark" title="Randomize")
57+
icon(name="sync" scale="1.5")
58+
59+
//
60+
div.my-1
61+
b Productivity score
62+
b-input-group.my-1(prepend="Points")
63+
b-form-input(v-model="editing.productivity")
64+
65+
hr
66+
4767
div.my-1
4868
b-btn(variant="danger", @click="removeClass(_class); $refs.edit.hide()")
4969
icon(name="trash")
@@ -58,6 +78,7 @@ import 'vue-awesome/icons/caret-right';
5878
import 'vue-awesome/icons/trash';
5979
import 'vue-awesome/icons/plus';
6080
import 'vue-awesome/icons/edit';
81+
import 'vue-awesome/icons/sync';
6182
6283
import _ from 'lodash';
6384
@@ -78,6 +99,8 @@ export default {
7899
name: null,
79100
rule: {},
80101
parent: [],
102+
inherit_color: true,
103+
color: null,
81104
},
82105
};
83106
},
@@ -140,6 +163,7 @@ export default {
140163
id: this.editing.id,
141164
name: this.editing.parent.concat(this.editing.name),
142165
rule: this.editing.rule.type !== null ? this.editing.rule : { type: null },
166+
data: { color: this.editing.inherit_color === true ? undefined : this.editing.color },
143167
};
144168
this.$store.commit('categories/updateClass', new_class);
145169
@@ -149,14 +173,21 @@ export default {
149173
});
150174
},
151175
resetModal() {
176+
const color = this._class.data ? this._class.data.color : undefined;
177+
const inherit_color = !color;
152178
this.editing = {
153179
id: this._class.id,
154180
name: this._class.subname,
155181
rule: _.cloneDeep(this._class.rule),
182+
color,
183+
inherit_color,
156184
parent: this._class.parent ? this._class.parent : [],
157185
};
158186
//console.log(this.editing);
159187
},
188+
randomColor() {
189+
this.editing.color = '#' + (0x1000000 + Math.random() * 0xffffff).toString(16).substr(1, 6);
190+
},
160191
},
161192
};
162193
</script>

src/util/classes.ts

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@ interface Category {
1414
name_pretty?: string;
1515
subname?: string;
1616
rule: Rule;
17+
data?: object;
1718
depth?: number;
1819
parent?: string[];
1920
children?: Category[];
2021
}
2122

2223
export const defaultCategories: Category[] = [
23-
{ name: ['Work'], rule: { type: 'regex', regex: 'Google Docs|libreoffice|ReText' } },
24+
{
25+
name: ['Work'],
26+
rule: { type: 'regex', regex: 'Google Docs|libreoffice|ReText' },
27+
data: { productivity: 5, color: '#0F0' },
28+
},
2429
{
2530
name: ['Work', 'Programming'],
2631
rule: { type: 'regex', regex: 'GitHub|Stack Overflow|BitBucket|Gitlab|vim|Spyder|kate' },
@@ -29,7 +34,11 @@ export const defaultCategories: Category[] = [
2934
name: ['Work', 'Programming', 'ActivityWatch'],
3035
rule: { type: 'regex', regex: 'ActivityWatch|aw-', ignore_case: true },
3136
},
32-
{ name: ['Media', 'Games'], rule: { type: 'regex', regex: 'Minecraft|RimWorld' } },
37+
{
38+
name: ['Media', 'Games'],
39+
rule: { type: 'regex', regex: 'Minecraft|RimWorld' },
40+
data: { color: '#0FF' },
41+
},
3342
{ name: ['Media', 'Video'], rule: { type: 'regex', regex: 'YouTube|Plex|VLC' } },
3443
{
3544
name: ['Media', 'Social Media'],
@@ -122,3 +131,16 @@ export function loadClassesForQuery(): [string[], Rule][] {
122131
return [c.name, c.rule];
123132
});
124133
}
134+
135+
export function matchString(str: string): Category | null {
136+
console.log(loadClasses());
137+
const matchingCats = loadClasses()
138+
.filter(c => c.rule.type == 'regex')
139+
.filter(c => {
140+
const re = RegExp(c.rule.regex, c.rule.ignore_case ? 'i' : '');
141+
return re.test(str);
142+
});
143+
// TODO: Pick deepest
144+
if (matchingCats.length > 0) return matchingCats[0];
145+
return null;
146+
}

src/util/color.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
'use strict';
22

33
import _ from 'lodash';
4+
import { matchString, loadClasses } from './classes';
45
const Color = require('color');
56
const d3 = require('d3');
67

@@ -59,6 +60,31 @@ export function getColorFromString(appname) {
5960
return customColors[appname] || scale(Math.abs(hashcode(appname) % 20));
6061
}
6162

63+
function getColorFromCategory(c, allCats) {
64+
if (c.data && c.data.color) {
65+
return c.data.color;
66+
} else if (c.name.slice(0, -1).length > 0) {
67+
// If no color is set on category, traverse parents until one is found
68+
const parent = c.name.slice(0, -1);
69+
const parentCat = allCats.find(cc => _.isEqual(cc.name, parent));
70+
return getColorFromCategory(parentCat);
71+
} else {
72+
// TODO: Fix reasonable fallback
73+
return '#F0F';
74+
}
75+
}
76+
77+
export function getCategoryColorFromString(str) {
78+
// TODO: Don't load classes on every call
79+
const allCats = loadClasses();
80+
const c = matchString(str);
81+
if (c !== null) {
82+
return getColorFromCategory(c, allCats);
83+
} else {
84+
return getColorFromString(str);
85+
}
86+
}
87+
6288
export function getTitleAttr(bucket, e) {
6389
if (bucket.type == 'currentwindow') {
6490
return e.data.app;

src/visualizations/summary.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ const d3 = require('d3');
44
const Color = require('color');
55
const _ = require('lodash');
66

7-
import { getColorFromString } from '../util/color.js';
7+
import { getCategoryColorFromString } from '../util/color.js';
88

99
import { seconds_to_duration } from '../util/time.js';
1010

@@ -58,7 +58,7 @@ function update(container, apps) {
5858
const width = (app.duration / longest_duration) * 100 + '%';
5959
const barHeight = 50;
6060
const textSize = 15;
61-
const baseappcolor = getColorFromString(app.colorKey || app.name);
61+
const baseappcolor = app.color || getCategoryColorFromString(app.colorKey || app.name);
6262
const appcolor = Color(baseappcolor).lighten(0.1).hex();
6363
const hovercolor = Color(baseappcolor).darken(0.1).hex();
6464

@@ -120,6 +120,7 @@ function updateSummedEvents(container, summedEvents, titleKeyFunc, hoverKeyFunc,
120120
name: titleKeyFunc(e),
121121
hovertext: hoverKeyFunc(e),
122122
duration: e.duration,
123+
color: e.data['$color'],
123124
colorKey: colorKeyFunc(e),
124125
};
125126
});

0 commit comments

Comments
 (0)