1
1
<template lang="pug">
2
2
div.mx-3
3
3
b-form
4
- b-form-group( label ="Bucket :" )
5
- select( v-model ="selectedBucket " )
6
- option( v-for ="bucket in buckets" , :value ="bucket.id " ) {{ bucket.id }}
4
+ b-form-group( label ="Host :" )
5
+ select( v-model ="selectedHost " )
6
+ option( v-for ="host in hostnames" : value= "host " ) {{ host }}
7
7
b-form-group( label ="Show:" )
8
8
select( v-model ="view" )
9
9
option( value ="timeGridDay" ) Day
@@ -15,26 +15,67 @@ div.mx-3
15
15
</template >
16
16
17
17
<script >
18
- import { getTitleAttr , getColorFromString } from ' ../util/color' ;
19
18
import moment from ' moment' ;
20
19
import _ from ' lodash' ;
21
20
import FullCalendar from ' @fullcalendar/vue' ;
22
21
import timeGridPlugin from ' @fullcalendar/timegrid' ;
23
22
23
+ import queries from ' ~/queries' ;
24
+ import { useCategoryStore } from ' ~/stores/categories' ;
25
+
26
+ function mergeAdjacent (events ) {
27
+ // process events, merging adjacent events with same category
28
+ const mergedEvents = [];
29
+ let lastEvent = null ;
30
+ for (let i = 0 ; i < events .length ; i++ ) {
31
+ const event = events[i];
32
+ if (lastEvent == null ) {
33
+ lastEvent = event ;
34
+ continue ;
35
+ }
36
+ // if adjacent with less than 10 seconds between, merge
37
+ const isAdjacent =
38
+ moment (event .timestamp ).diff (
39
+ moment (lastEvent .timestamp ).add (lastEvent .duration , ' seconds' ),
40
+ ' seconds'
41
+ ) < 10 ;
42
+ if (
43
+ isAdjacent &&
44
+ event .data [' $category' ].join (' > ' ) == lastEvent .data [' $category' ].join (' > ' )
45
+ ) {
46
+ lastEvent .duration += event .duration ;
47
+ } else {
48
+ mergedEvents .push (lastEvent);
49
+ lastEvent = event ;
50
+ }
51
+ }
52
+ if (lastEvent != null ) mergedEvents .push (lastEvent);
53
+ return mergedEvents;
54
+ }
55
+
24
56
// TODO: Use canonical timeline query, with flooding and categorization
25
57
// TODO: Checkbox for toggling category-view, where adjacent events with same category are merged and the events are labeled by category
26
58
// TODO: Use the recommended way of dynamically getting events: https://fullcalendar.io/docs/events-function
27
59
export default {
28
60
components: {
29
- FullCalendar, // make the <FullCalendar> tag available
61
+ FullCalendar,
30
62
},
31
63
props: {
32
64
buckets: { type: Array },
33
65
},
34
66
data () {
35
- return { fitToActive: false , selectedBucket: null , view: ' timeGridDay' };
67
+ return {
68
+ events: [],
69
+ fitToActive: false ,
70
+ selectedHost: ' erb-m2.localdomain' ,
71
+ view: ' timeGridWeek' ,
72
+ };
36
73
},
37
74
computed: {
75
+ hostnames : function () {
76
+ if (this .buckets == null ) return [];
77
+ return _ .uniq (this .buckets .map (b => b .hostname ).filter (h => h != null ));
78
+ },
38
79
calendarOptions : function () {
39
80
const events = this .events ;
40
81
const first = _ .minBy (events, e => e .start );
@@ -67,37 +108,73 @@ export default {
67
108
},
68
109
};
69
110
},
70
- events : function () {
71
- // NOTE: This returns FullCalendar events, not ActivityWatch events.
72
- if (this .buckets == null ) return [];
73
-
74
- const bucket = _ .find (this .buckets , b => b .id == this .selectedBucket );
75
- if (bucket == null ) {
76
- return ;
77
- }
78
- let events = bucket .events ;
79
- events = _ .filter (events, e => e .duration > 10 );
80
- events = _ .map (events, e => {
81
- return {
82
- title: getTitleAttr (bucket, e),
83
- start: moment (e .timestamp ).format (),
84
- end: moment (e .timestamp ).add (e .duration , ' seconds' ).format (),
85
- backgroundColor: getColorFromString (getTitleAttr (bucket, e)),
86
- };
87
- });
88
- return events;
111
+ queryOptions : function () {
112
+ return {
113
+ hostname: this .selectedHost ,
114
+ filter_afk: true ,
115
+ start: moment ().startOf (' week' ).format (),
116
+ stop: moment ().endOf (' week' ).format (),
117
+ };
89
118
},
90
119
},
91
120
watch: {
92
121
view : function (to ) {
93
122
const calendar = this .$refs .fullCalendar .getApi ();
94
123
calendar .changeView (to);
95
124
},
125
+ selectedHost : async function () {
126
+ console .log (' selectedHost changed' );
127
+ this .events = await this .loadEventsCanonical ();
128
+ },
129
+ },
130
+ mounted : async function () {
131
+ this .events = await this .loadEventsCanonical ();
96
132
},
97
133
methods: {
98
134
onEventClick : function (arg ) {
99
135
// TODO: Open event inspector/editor here
100
- alert (' event click! ' + JSON .stringify (arg .event ));
136
+ alert (' event click!\n ' + JSON .stringify (arg .event , null , 2 ));
137
+ },
138
+ loadEventsCanonical : async function () {
139
+ console .log (' loadEventsCanonical' );
140
+ console .log (this .queryOptions .hostname );
141
+ if (this .queryOptions .hostname == null ) return [];
142
+
143
+ const categoryStore = useCategoryStore ();
144
+ categoryStore .load ();
145
+ const categories = categoryStore .classes_for_query ;
146
+
147
+ let query = queries .canonicalEvents ({
148
+ bid_window: ' aw-watcher-window_' + this .queryOptions .hostname ,
149
+ bid_afk: ' aw-watcher-afk_' + this .queryOptions .hostname ,
150
+ filter_afk: this .queryOptions .filter_afk ,
151
+ categories,
152
+ });
153
+ query += ' RETURN = events;' ;
154
+ console .log (query);
155
+ query = query .split (' ;' ).map (s => s .trim () + ' ;' );
156
+
157
+ const timeperiods = [
158
+ moment (this .queryOptions .start ).format () + ' /' + moment (this .queryOptions .stop ).format (),
159
+ ];
160
+ console .log (' Querying' );
161
+ const data = await this .$aw .query (timeperiods, query);
162
+ console .log (data);
163
+ let events = _ .orderBy (data[0 ], [' timestamp' ], [' desc' ]);
164
+
165
+ events = mergeAdjacent (events);
166
+ console .log (' mergedEvents' , events);
167
+
168
+ events = _ .filter (events, e => e .duration > 60 );
169
+ events = _ .map (events, e => {
170
+ return {
171
+ title: e .data [' $category' ].join (' > ' ),
172
+ start: moment (e .timestamp ).format (),
173
+ end: moment (e .timestamp ).add (e .duration , ' seconds' ).format (),
174
+ backgroundColor: categoryStore .get_category_color (e .data [' $category' ]),
175
+ };
176
+ });
177
+ return events;
101
178
},
102
179
},
103
180
};
0 commit comments