From 1dfc2906e40f18444869ace29ed17c6697f73d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Bj=C3=A4reholt?= Date: Wed, 6 Jul 2022 09:22:44 +0200 Subject: [PATCH] feat: added toggle for enabling multidevice queries --- src/stores/activity.ts | 19 +++--- src/stores/buckets.ts | 69 ++++++++++------------ src/stores/settings.ts | 2 + src/views/settings/DeveloperSettings.vue | 12 ++++ src/views/settings/LandingPageSettings.vue | 2 +- 5 files changed, 56 insertions(+), 48 deletions(-) diff --git a/src/stores/activity.ts b/src/stores/activity.ts index ef144bf8..d80b1bb4 100644 --- a/src/stores/activity.ts +++ b/src/stores/activity.ts @@ -164,17 +164,15 @@ export const useActivityStore = defineStore('activity', { // TODO: These queries can actually run in parallel, but since server won't process them in parallel anyway we won't. await this.set_available(query_options); - // TODO: Move me - const multidevice = true; - if (this.window.available) { - if (multidevice) { + if (settingsStore.useMultidevice) { const hostnames = bucketsStore.hosts.filter( // require that the host has window buckets, // and that the host is not a fakedata host, // unless we're explicitly querying fakedata host => - bucketsStore.windowBucketsByHost(host).length > 0 && + host && + bucketsStore.bucketsWindow(host).length > 0 && (!host.startsWith('fakedata') || query_options.host.startsWith('fakedata')) ); console.info('Including hosts in multiquery: ', hostnames); @@ -463,11 +461,12 @@ export const useActivityStore = defineStore('activity', { async get_buckets({ host }) { // TODO: Move to bucketStore on a per-host basis? const bucketsStore = useBucketsStore(); - this.buckets.afk = bucketsStore.afkBucketsByHost(host); - this.buckets.window = bucketsStore.windowBucketsByHost(host); - this.buckets.android = bucketsStore.androidBucketsByHost(host); - this.buckets.browser = bucketsStore.browserBuckets; - this.buckets.editor = bucketsStore.editorBuckets; + this.buckets.afk = bucketsStore.bucketsAFK(host); + this.buckets.window = bucketsStore.bucketsWindow(host); + this.buckets.android = bucketsStore.bucketsAndroid(host); + this.buckets.browser = bucketsStore.bucketsBrowser(host); + this.buckets.editor = bucketsStore.bucketsEditor(host); + console.log('Available buckets: ', this.buckets); this.buckets.loaded = true; }, diff --git a/src/stores/buckets.ts b/src/stores/buckets.ts index 90b7b2e1..87349694 100644 --- a/src/stores/buckets.ts +++ b/src/stores/buckets.ts @@ -4,16 +4,12 @@ import { IBucket } from '~/util/interfaces'; import { defineStore } from 'pinia'; import { getClient } from '~/util/awclient'; -function get_buckets_by_type(buckets: IBucket[], type: string) { +function select_buckets(buckets: IBucket[], { host, type }: { host?: string; type?: string }) { return _.map( - _.filter(buckets, bucket => bucket['type'] === type), - bucket => bucket['id'] - ); -} - -function get_buckets_by_host_and_type(buckets: IBucket[], host: string, type: string) { - return _.map( - _.filter(buckets, bucket => bucket['type'] === type && bucket['hostname'] == host), + _.filter( + buckets, + bucket => (!type || bucket['type'] === type) && (!host || bucket['hostname'] == host) + ), bucket => bucket['id'] ); } @@ -34,10 +30,12 @@ export const useBucketsStore = defineStore('buckets', { return _.uniq(_.map(this.buckets, bucket => bucket['device_id'])); }, - availableByHost(): (hostname: string) => { + available(): (hostname: string) => { window: boolean; browser: boolean; editor: boolean; + android: boolean; + category: boolean; } { // Returns a map of which kinds of buckets are available // @@ -45,57 +43,54 @@ export const useBucketsStore = defineStore('buckets', { // 'browser' requires (currentwindow + afk + browser) buckets // 'editor' requires editor buckets return hostname => { - const windowAvailable = - this.windowBucketsByHost(hostname).length > 0 && - this.afkBucketsByHost(hostname).length > 0; + const windowAvail = + this.bucketsWindow(hostname).length > 0 && this.bucketsAFK(hostname).length > 0; + const androidAvail = this.bucketsAndroid(hostname).length > 0; return { - window: windowAvailable, - browser: windowAvailable && this.browserBuckets(hostname).length > 0, - editor: this.editorBuckets(hostname).length > 0, + window: windowAvail, + browser: window && this.bucketsBrowser(hostname).length > 0, + editor: this.bucketsEditor(hostname).length > 0, + android: androidAvail, + category: windowAvail || androidAvail, }; }; }, - availablePerHost(): { - [hostname: string]: { window: boolean; browser: boolean; editor: boolean }; - } { - // Returns a map {hostname: {[eg. window, browser, editor]: boolean}} that contains available bucket types for all hosts - // So we want to map over the hosts, and let the values be the result of the availableByHost function for each host. - return Object.assign({}, ...this.hosts().map(this.availableByHost())); - }, - // These should be considered low-level, and should be used sparingly. - afkBucketsByHost() { - return (host: string) => get_buckets_by_host_and_type(this.buckets, host, 'afkstatus'); + bucketsAFK() { + return (host: string) => select_buckets(this.buckets, { host, type: 'afkstatus' }); }, - windowBucketsByHost() { + bucketsWindow() { return (host: string) => _.filter( - get_buckets_by_host_and_type(this.buckets, host, 'currentwindow'), + select_buckets(this.buckets, { host, type: 'currentwindow' }), id => !id.startsWith('aw-watcher-android') ); }, - androidBucketsByHost() { - return host => - _.filter(get_buckets_by_host_and_type(this.buckets, host, 'currentwindow'), id => + bucketsAndroid() { + return (host: string) => + _.filter(select_buckets(this.buckets, { host, type: 'currentwindow' }), id => id.startsWith('aw-watcher-android') ); }, - editorBuckets() { + bucketsEditor() { // fallback to a bucket with 'unknown' host, if one exists. // TODO: This needs a fix so we can get rid of this workaround. + const type = 'app.editor.activity'; return (host: string) => - get_buckets_by_host_and_type(this.buckets, host, 'app.editor.activity') || - get_buckets_by_host_and_type(this.buckets, 'unknown', 'app.editor.activity'); + select_buckets(this.buckets, { host, type }) || + select_buckets(this.buckets, { host: 'unknown', type }); }, - browserBuckets() { + bucketsBrowser() { // fallback to a bucket with 'unknown' host, if one exists. // TODO: This needs a fix so we can get rid of this workaround. + const type = 'web.tab.current'; return (host: string) => - get_buckets_by_host_and_type(this.buckets, host, 'web.tab.current') || - get_buckets_by_host_and_type(this.buckets, 'unknown', 'web.tab.current'); + select_buckets(this.buckets, { host, type }) || + select_buckets(this.buckets, { host: 'unknown', type }); }, + getBucket() { return (id: string) => _.filter(this.buckets, b => b.id === id)[0]; }, diff --git a/src/stores/settings.ts b/src/stores/settings.ts index 33579a9a..0cfac895 100644 --- a/src/stores/settings.ts +++ b/src/stores/settings.ts @@ -23,6 +23,7 @@ interface State { // Whether to show certain WIP features devmode: boolean; showYearly: boolean; + useMultidevice: boolean; // Set to true if settings loaded _loaded: boolean; @@ -48,6 +49,7 @@ export const useSettingsStore = defineStore('settings', { // NOTE: PRODUCTION might be undefined (in tests, for example) devmode: typeof PRODUCTION === 'undefined' ? true : !PRODUCTION, showYearly: false, + useMultidevice: false, _loaded: false, }), diff --git a/src/views/settings/DeveloperSettings.vue b/src/views/settings/DeveloperSettings.vue index 23d48275..14ddc380 100644 --- a/src/views/settings/DeveloperSettings.vue +++ b/src/views/settings/DeveloperSettings.vue @@ -18,6 +18,10 @@ div b-form-group(label="Show yearly time range" label-cols-md=3 description="Querying an entire year is a very heavy operation, and is likely to lead to timeouts. However, the query might be fast enough if you're running aw-server-rust.") div b-form-checkbox.float-right.ml-2(v-model="showYearly" switch) + + b-form-group(label="Use multidevice query" label-cols-md=3 description="Multidevice query is where events are collected from several hosts in the Activity view. It is an early experiment, that currently does not support browser buckets (or the audible-as-active feature).") + div + b-form-checkbox.float-right.ml-2(v-model="useMultidevice" switch) diff --git a/src/views/settings/LandingPageSettings.vue b/src/views/settings/LandingPageSettings.vue index 41cef1a5..7bbaeac8 100644 --- a/src/views/settings/LandingPageSettings.vue +++ b/src/views/settings/LandingPageSettings.vue @@ -39,7 +39,7 @@ export default { }, }, hostnames() { - return Object.keys(this.bucketsStore.bucketsByHostname); + return this.bucketsStore.hosts; }, }, async mounted() {