Skip to content

Commit 6379134

Browse files
Merge pull request #186 from ActivityWatch/dev/make-queries-less-dependent
See host even if only editor buckets exist
2 parents 3451196 + f167565 commit 6379134

5 files changed

Lines changed: 155 additions & 76 deletions

File tree

src/components/Header.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ export default {
103103
//console.log(types_by_host);
104104
105105
_.each(types_by_host, (types, hostname) => {
106-
if (types.afk && types.window) {
106+
if (hostname != 'unknown') {
107107
this.activityViews.push({
108108
name: hostname,
109109
hostname: hostname,

src/store/modules/activity_daily.ts

Lines changed: 107 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,12 @@ const _state = {
5656
browser_buckets: 'all',
5757
editor_buckets: 'all',
5858
},
59-
editor_buckets_available: [],
60-
browser_buckets_available: [],
59+
buckets: {
60+
afk_buckets: [],
61+
window_buckets: [],
62+
editor_buckets: [],
63+
browser_buckets: [],
64+
},
6165
};
6266

6367
function timeperiodsAroundTimeperiod(timeperiod: TimePeriod): TimePeriod[] {
@@ -100,95 +104,144 @@ const actions = {
100104
if (!query_options.timeperiod) {
101105
query_options.timeperiod = dateToTimeperiod(query_options.date);
102106
}
107+
108+
await dispatch('buckets/ensureBuckets', null, { root: true });
103109
await dispatch('get_buckets', query_options);
104110

105111
// TODO: These queries can actually run in parallel, but since server won't process them in parallel anyway we won't.
106-
await dispatch('query_window', query_options);
107-
await dispatch('query_browser', query_options);
108-
await dispatch('query_editor', query_options);
109-
await dispatch('query_active_history', query_options);
112+
113+
if (state.buckets.afk_buckets.length > 0 && state.buckets.window_buckets.length > 0) {
114+
await dispatch('query_window', query_options);
115+
} else {
116+
console.log('Cannot call query_window as we are missing either an afk or window bucket');
117+
await dispatch('query_window_empty', query_options);
118+
}
119+
120+
if (
121+
state.buckets.afk_buckets.length > 0 &&
122+
state.buckets.window_buckets.length > 0 &&
123+
state.buckets.browser_buckets.length > 0
124+
) {
125+
await dispatch('query_browser', query_options);
126+
} else {
127+
console.log(
128+
'Cannot call query_browser as we are missing either an afk, window or browser bucket'
129+
);
130+
await dispatch('query_browser_empty', query_options);
131+
}
132+
133+
if (state.buckets.afk_buckets.length > 0) {
134+
await dispatch('query_active_history', query_options);
135+
} else {
136+
console.log('Cannot call query_active_history as we do not have an afk bucket');
137+
await dispatch('query_active_history_empty', query_options);
138+
}
139+
140+
if (state.buckets.editor_buckets.length > 0) {
141+
await dispatch('query_editor', query_options);
142+
} else {
143+
console.log('Cannot call query_editor as we do not have any editor buckets');
144+
await dispatch('query_editor_empty', query_options);
145+
}
110146
} else {
111147
console.warn(
112148
'ensure_loaded called twice with same query_options but without query_options.force = true, skipping...'
113149
);
114150
}
115151
},
116152

117-
async query_window({ commit }, { host, timeperiod, filterAFK, filterCategories }: QueryOptions) {
118-
const start = moment();
153+
async query_window({ state, commit }, { timeperiod, filterAFK, filterCategories }: QueryOptions) {
119154
const periods = [timeperiodToStr(timeperiod)];
120155
const classes = loadClassesForQuery();
121-
const bucket_id_window = 'aw-watcher-window_' + host;
122-
const bucket_id_afk = 'aw-watcher-afk_' + host;
123156
const q = queries.windowQuery(
124-
bucket_id_window,
125-
bucket_id_afk,
157+
state.buckets.window_buckets[0],
158+
state.buckets.afk_buckets[0],
126159
default_limit, // this.top_apps_count,
127160
default_limit, // this.top_windowtitles_count,
128161
filterAFK,
129162
classes,
130163
filterCategories
131164
);
132165
const data = await this._vm.$aw.query(periods, q);
133-
console.info(`Completed window query in ${moment().diff(start)}ms`);
134166
commit('query_window_completed', data[0]);
135167
},
136168

137-
async query_browser({ state, commit }, { host, timeperiod, filterAFK }: QueryOptions) {
138-
const start = moment();
139-
if (state.browser_buckets_available) {
140-
const periods = [timeperiodToStr(timeperiod)];
141-
const bucket_id_window = 'aw-watcher-window_' + host;
142-
const bucket_id_afk = 'aw-watcher-afk_' + host;
143-
const q = queries.browserSummaryQuery(
144-
state.browser_buckets_available,
145-
bucket_id_window,
146-
bucket_id_afk,
147-
default_limit, // this.top_web_count
148-
filterAFK
149-
);
150-
const data = await this._vm.$aw.query(periods, q);
151-
console.info(`Completed browser query in ${moment().diff(start)}ms`);
152-
commit('query_browser_completed', data[0]);
153-
}
169+
async query_window_empty({ commit }) {
170+
const data = {
171+
app_events: [],
172+
title_events: [],
173+
cat_events: [],
174+
duration: 0,
175+
active_events: [],
176+
};
177+
commit('query_window_completed', data);
178+
},
179+
180+
async query_browser({ state, commit }, { timeperiod, filterAFK }: QueryOptions) {
181+
const periods = [timeperiodToStr(timeperiod)];
182+
const q = queries.browserSummaryQuery(
183+
state.buckets.browser_buckets,
184+
state.buckets.window_buckets[0],
185+
state.buckets.afk_buckets[0],
186+
default_limit, // this.top_web_count
187+
filterAFK
188+
);
189+
const data = await this._vm.$aw.query(periods, q);
190+
commit('query_browser_completed', data[0]);
191+
},
192+
193+
async query_browser_empty({ commit }) {
194+
const data = {
195+
domains: [],
196+
urls: [],
197+
duration: 0,
198+
};
199+
commit('query_browser_completed', data);
154200
},
155201

156202
async query_editor({ state, commit }, { timeperiod }) {
157-
if (state.editor_buckets_available) {
158-
const periods = [timeperiodToStr(timeperiod)];
159-
const q = queries.editorActivityQuery(state.editor_buckets_available, 100);
160-
const data = await this._vm.$aw.query(periods, q).catch(this.errorHandler);
161-
commit('query_editor_completed', data[0]);
162-
}
203+
const periods = [timeperiodToStr(timeperiod)];
204+
const q = queries.editorActivityQuery(state.buckets.editor_buckets, 100);
205+
const data = await this._vm.$aw.query(periods, q);
206+
commit('query_editor_completed', data[0]);
163207
},
164208

165-
async query_active_history({ commit, state }, { host, timeperiod }: QueryOptions) {
209+
async query_editor_empty({ commit }) {
210+
const data = {
211+
files: [],
212+
projects: [],
213+
languages: [],
214+
};
215+
commit('query_editor_completed', data);
216+
},
217+
218+
async query_active_history({ commit, state }, { timeperiod }: QueryOptions) {
166219
const periods = timeperiodStrsAroundTimeperiod(timeperiod).filter(tp_str => {
167220
return !_.includes(state.active_history, tp_str);
168221
});
169-
const bucket_id_afk = 'aw-watcher-afk_' + host;
170-
const queryStart = moment();
222+
const bucket_id_afk = state.buckets.afk_buckets[0];
171223
const data = await this._vm.$aw.query(periods, queries.dailyActivityQuery(bucket_id_afk));
172224
const active_history = _.zipObject(
173225
periods,
174226
_.map(data, pair => _.filter(pair, e => e.data.status == 'not-afk'))
175227
);
176-
console.info(`Completed history query in ${moment().diff(queryStart)}ms`);
177228
commit('query_active_history_completed', { active_history });
178229
},
179230

180-
async get_buckets({ commit }) {
181-
const buckets = await this._vm.$aw.getBuckets();
182-
const browser_buckets = _.map(
183-
_.filter(buckets, bucket => bucket['type'] === 'web.tab.current'),
184-
bucket => bucket['id']
185-
);
186-
const editor_buckets = _.map(
187-
_.filter(buckets, bucket => bucket['type'] === 'app.editor.activity'),
188-
bucket => bucket['id']
189-
);
190-
commit('browser_buckets', browser_buckets);
191-
commit('editor_buckets', editor_buckets);
231+
async query_active_history_empty({ commit }) {
232+
const data = [];
233+
commit('query_active_history_completed', data);
234+
},
235+
236+
async get_buckets({ commit, rootGetters }, { host }) {
237+
const buckets = {
238+
afk_buckets: rootGetters['buckets/afkBucketsByHost'](host),
239+
window_buckets: rootGetters['buckets/windowBucketsByHost'](host),
240+
browser_buckets: rootGetters['buckets/browserBuckets'],
241+
editor_buckets: rootGetters['buckets/editorBuckets'],
242+
};
243+
console.log('Available buckets: ', buckets);
244+
commit('buckets', buckets);
192245
},
193246

194247
async load_demo({ commit }) {
@@ -409,12 +462,8 @@ const mutations = {
409462
};
410463
},
411464

412-
browser_buckets(state, data) {
413-
state.browser_buckets_available = data;
414-
},
415-
416-
editor_buckets(state, data) {
417-
state.editor_buckets_available = data;
465+
buckets(state, data) {
466+
state.buckets = data;
418467
},
419468
};
420469

src/store/modules/buckets.js

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,39 @@ const state = {
33
buckets: [],
44
};
55

6+
function get_buckets_by_type(buckets, type) {
7+
return _.map(
8+
_.filter(buckets, bucket => bucket['type'] === type),
9+
bucket => bucket['id']
10+
);
11+
}
12+
13+
function get_buckets_by_host_and_type(buckets, host, type) {
14+
return _.map(
15+
_.filter(buckets, bucket => bucket['type'] === type && bucket['hostname'] == host),
16+
bucket => bucket['id']
17+
);
18+
}
19+
620
// getters
721
const getters = {
22+
afkBuckets(state) {
23+
return get_buckets_by_type(state.buckets, 'afkstatus');
24+
},
25+
afkBucketsByHost: state => host => {
26+
return get_buckets_by_host_and_type(state.buckets, host, 'afkstatus');
27+
},
28+
windowBuckets(state) {
29+
return get_buckets_by_type(state.buckets, 'currentwindow');
30+
},
31+
windowBucketsByHost: state => host => {
32+
return get_buckets_by_host_and_type(state.buckets, host, 'currentwindow');
33+
},
34+
editorBuckets(state) {
35+
return get_buckets_by_type(state.buckets, 'app.editor.activity');
36+
},
837
browserBuckets(state) {
9-
return _.map(
10-
_.filter(state.buckets, bucket => bucket['type'] === 'web.tab.current'),
11-
bucket => bucket['id']
12-
);
38+
return get_buckets_by_type(state.buckets, 'web.tab.current');
1339
},
1440
getBucket: state => id => _.filter(state.buckets, b => b.id === id)[0],
1541
bucketsByHostname: state => _.groupBy(state.buckets, 'hostname'),
@@ -25,7 +51,6 @@ const actions = {
2551

2652
async loadBuckets({ commit }) {
2753
const buckets = await this._vm.$aw.getBuckets();
28-
console.info('Received buckets: ', buckets);
2954
commit('update_buckets', buckets);
3055
},
3156

src/views/activity/daily/ActivityDailyBrowser.vue

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,31 @@
11
<template lang="pug">
22
div
33
// TODO: Add back option to select a specific browser bucket
4+
div(v-if="browserBuckets.length <= 0")
5+
h6 No browser buckets available
6+
small Make sure you have a browser watcher installed to use this feature
7+
div(v-if="browserBuckets.length > 0")
48

5-
h6 Active browser time: {{ $store.state.activity_daily.browser_duration | friendlyduration }}
9+
h6 Active browser time: {{ $store.state.activity_daily.browser_duration | friendlyduration }}
610

7-
div.row
8-
div.col-md-6
9-
h5 Top Browser Domains
10-
div(v-if="browserBuckets")
11-
aw-summary(:fields="$store.state.activity_daily.top_domains", :namefunc="e => e.data.$domain", :colorfunc="e => e.data.$domain", with_limit)
11+
div.row
12+
div.col-md-6
13+
h5 Top Browser Domains
14+
div(v-if="browserBuckets")
15+
aw-summary(:fields="$store.state.activity_daily.top_domains", :namefunc="e => e.data.$domain", :colorfunc="e => e.data.$domain", with_limit)
1216

13-
div.col-md-6
14-
h5 Top Browser URLs
15-
div(v-if="browserBuckets")
16-
aw-summary(:fields="$store.state.activity_daily.top_urls", :namefunc="e => e.data.url", :colorfunc="e => e.data.$domain", with_limit)
17+
div.col-md-6
18+
h5 Top Browser URLs
19+
div(v-if="browserBuckets")
20+
aw-summary(:fields="$store.state.activity_daily.top_urls", :namefunc="e => e.data.url", :colorfunc="e => e.data.$domain", with_limit)
1721

1822
//div(v-if="periodLength === 'day'")
1923
br
2024
hr
2125
b-form-checkbox(v-model="timelineShowAFK")
2226
| Show AFK time
2327
aw-timeline-inspect(:chunks="$store.state.activity_daily.web_chunks", :show_afk='timelineShowAFK', :chunkfunc='e => e.data.$domain', :eventfunc='e => e.data.url')
28+
br
2429
</template>
2530

2631
<script>
@@ -44,7 +49,7 @@ export default {
4449
},
4550
computed: {
4651
browserBuckets: function() {
47-
return this.$store.state.activity_daily.browser_buckets_available;
52+
return this.$store.state.activity_daily.buckets.browser_buckets;
4853
},
4954
},
5055
};

src/views/activity/daily/ActivityDailyEditor.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ export default {
6363
6464
computed: {
6565
editorBuckets: function() {
66-
return this.$store.state.activity_daily.editor_buckets_available;
66+
return this.$store.state.activity_daily.buckets.editor_buckets;
6767
},
6868
dateEnd: function() {
6969
return moment(this.date)

0 commit comments

Comments
 (0)