Skip to content

Commit ec2c385

Browse files
committed
feat: continued working on category colors
1 parent 0ef8936 commit ec2c385

File tree

14 files changed

+86
-34
lines changed

14 files changed

+86
-34
lines changed

package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@
119119
"vis-util": "^4.3.2",
120120
"vue-awesome": "^3.5.1",
121121
"vue-chartjs": "^3.5.0",
122-
"vue-d3-sunburst": "^1.0.1",
122+
"vue-d3-sunburst": "^1.1.0",
123123
"vue-datetime": "^1.0.0-beta.13",
124124
"vue-property-decorator": "^8.5.1",
125125
"vuedraggable": "^2.24.3",

src/components/SelectableVisualization.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ div
3131
div(v-if="type == 'top_titles'")
3232
aw-summary(:fields="$store.state.activity.window.top_titles",
3333
:namefunc="e => e.data.title",
34-
:colorfunc="e => e.data.app",
34+
:colorfunc="e => e.data.title",
3535
with_limit)
3636
div(v-if="type == 'top_domains'")
3737
aw-summary(:fields="$store.state.activity.browser.top_domains",

src/store/modules/categories.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,9 @@ const getters = {
3232
v => v.join('>>>>') // Can be any separator that doesn't appear in the category names themselves
3333
);
3434
},
35+
get_category: state => category_arr => {
36+
return state.classes.find(c => _.isEqual(c.name, category_arr));
37+
},
3538
};
3639

3740
// actions

src/util/classes.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,13 @@ interface Rule {
88
ignore_case?: boolean;
99
}
1010

11-
interface Category {
11+
export interface Category {
1212
id?: number;
1313
name: string[];
1414
name_pretty?: string;
1515
subname?: string;
1616
rule: Rule;
17-
data?: object;
17+
data?: any;
1818
depth?: number;
1919
parent?: string[];
2020
children?: Category[];
@@ -50,6 +50,7 @@ export const defaultCategories: Category[] = [
5050
rule: { type: 'regex', regex: 'Messenger|Telegram|Signal|WhatsApp|Rambox|Slack|Riot|Discord' },
5151
},
5252
{ name: ['Comms', 'Email'], rule: { type: 'regex', regex: 'Gmail|Thunderbird|mutt|alpine' } },
53+
{ name: ['Uncategorized'], rule: { type: null }, data: { color: '#ccc' } },
5354
];
5455

5556
export function build_category_hierarchy(classes: Category[]): Category[] {
@@ -132,15 +133,23 @@ export function loadClassesForQuery(): [string[], Rule][] {
132133
});
133134
}
134135

135-
export function matchString(str: string): Category | null {
136-
console.log(loadClasses());
137-
const matchingCats = loadClasses()
136+
function pickDeepest(categories: Category[]) {
137+
return _.maxBy(categories, c => c.name.length);
138+
}
139+
140+
export function matchString(str: string, categories: Category[] | null): Category | null {
141+
if (!categories) {
142+
console.log(
143+
'Categories not passed, loading... (if you see this outside of a test, you should probably pass them)'
144+
);
145+
categories = loadClasses();
146+
}
147+
const matchingCats = categories
138148
.filter(c => c.rule.type == 'regex')
139149
.filter(c => {
140150
const re = RegExp(c.rule.regex, c.rule.ignore_case ? 'i' : '');
141151
return re.test(str);
142152
});
143-
// TODO: Pick deepest
144-
if (matchingCats.length > 0) return matchingCats[0];
153+
if (matchingCats.length > 0) return pickDeepest(matchingCats);
145154
return null;
146155
}
Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
1-
'use strict';
2-
31
import _ from 'lodash';
4-
import { matchString, loadClasses } from './classes';
2+
import { Category, matchString, loadClasses } from './classes';
53
const Color = require('color');
64
const d3 = require('d3');
75

86
// See here for examples:
97
// https://bl.ocks.org/pstuffa/3393ff2711a53975040077b7453781a9
108

119
const scale = d3.scaleOrdinal(['#90CAF9', '#FFE082', '#EF9A9A', '#A5D6A7']);
10+
const uncatColor = '#AAA';
1211

1312
// Needed to prewarm the color table
1413
scale.domain([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]);
@@ -60,28 +59,31 @@ export function getColorFromString(appname) {
6059
return customColors[appname] || scale(Math.abs(hashcode(appname) % 20));
6160
}
6261

63-
function getColorFromCategory(c, allCats) {
64-
if (c.data && c.data.color) {
62+
// TODO: Move into vuex?
63+
export function getColorFromCategory(c: Category, allCats: Category[]): string {
64+
if (c && c.data && c.data.color) {
6565
return c.data.color;
66-
} else if (c.name.slice(0, -1).length > 0) {
66+
} else if (c && c.name.slice(0, -1).length > 0) {
6767
// If no color is set on category, traverse parents until one is found
6868
const parent = c.name.slice(0, -1);
6969
const parentCat = allCats.find(cc => _.isEqual(cc.name, parent));
70-
return getColorFromCategory(parentCat);
70+
return getColorFromCategory(parentCat, allCats);
7171
} else {
7272
// TODO: Fix reasonable fallback
73-
return '#F0F';
73+
return uncatColor;
7474
}
7575
}
7676

77-
export function getCategoryColorFromString(str) {
77+
// TODO: Move into vuex?
78+
export function getCategoryColorFromString(str: string): string {
7879
// TODO: Don't load classes on every call
7980
const allCats = loadClasses();
80-
const c = matchString(str);
81+
const c = matchString(str, allCats);
8182
if (c !== null) {
8283
return getColorFromCategory(c, allCats);
8384
} else {
84-
return getColorFromString(str);
85+
// TODO: Fix reasonable fallback
86+
return uncatColor;
8587
}
8688
}
8789

src/visualizations/SunburstCategories.vue

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// We want to use another colorscheme than the default 'schemeAccent',
33
// unfortunately it seems like the color-scheme prop is broken.
44
// See this issue: https://github.com/David-Desmaisons/Vue.D3.sunburst/issues/11
5-
sunburst(:data="data")
5+
sunburst(:data="data", :colorScale="(s) => colorfunc(s)", :getCategoryForColor="categoryForColor", :colorScheme="null")
66
// Add behaviors
77
template(slot-scope="{ on, actions }")
88
highlightOnHover(v-bind="{ on, actions }")
@@ -31,6 +31,7 @@ import {
3131
zoomOnClick,
3232
} from 'vue-d3-sunburst';
3333
import 'vue-d3-sunburst/dist/vue-d3-sunburst.css';
34+
import { getColorFromCategory } from '~/util/color';
3435
3536
const example_data = {
3637
name: 'flare',
@@ -56,6 +57,8 @@ const example_data = {
5657
],
5758
};
5859
60+
const SEP = '>';
61+
5962
export default {
6063
components: {
6164
breadcrumbTrail,
@@ -70,6 +73,19 @@ export default {
7073
default: () => example_data,
7174
},
7275
},
76+
methods: {
77+
categoryForColor: function (d) {
78+
const category = d.parent ? d.parent.concat([d.name]) : [d.name];
79+
return category.join(SEP);
80+
},
81+
colorfunc: function (s) {
82+
if (s == 'All') return '#FFF';
83+
const cat = this.$store.getters['categories/get_category'](s.split(SEP));
84+
const allCats = this.$store.state.categories.classes;
85+
const color = getColorFromCategory(cat, allCats);
86+
return color;
87+
},
88+
},
7389
};
7490
</script>
7591

src/visualizations/VisTimeline.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import _ from 'lodash';
2727
import moment from 'moment';
2828
import Color from 'color';
2929
import { buildTooltip } from '../util/tooltip.js';
30-
import { getColorFromString, getTitleAttr } from '../util/color.js';
30+
import { getColorFromString, getTitleAttr } from '../util/color';
3131
3232
import { Timeline } from 'vis-timeline/esnext';
3333
import 'vis-timeline/styles/vis-timeline-graph2d.css';

src/visualizations/summary.js

Lines changed: 3 additions & 4 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 { getCategoryColorFromString } from '../util/color.js';
7+
import { getCategoryColorFromString } from '../util/color';
88

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

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

6564
// The group representing an application in the barchart
6665
const eg = svg.append('g');

src/visualizations/sunburst-clock.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const d3 = require('d3');
1818
const moment = require('moment');
1919

2020
import { seconds_to_duration } from '../util/time.js';
21-
const color = require('../util/color.js');
21+
const color = require('../util/color');
2222

2323
// Dimensions of sunburst.
2424
const width = 750;

0 commit comments

Comments
 (0)