11<template lang="pug">
22div
33 div
4- b-alert( v-if ="mode == 'range' && invalidDaterange" , variant ="warning" , show )
4+ b-alert( v-if ="invalidDaterange" , variant ="warning" , show )
55 | The selected date range is invalid. The second date must be greater or equal to the first date.
6- b-alert( v-if ="mode == 'range' && daterangeTooLong" , variant ="warning" , show )
6+ b-alert( v-if ="daterangeTooLong" , variant ="warning" , show )
77 | The selected date range is too long. The maximum is {{ maxDuration/(24*60*60) }} days.
88
9- div.d-flex.justify-content-between.align-items-end
9+ div.d-flex.justify-content-between
1010 table
1111 tr
12- th.pr-2
13- label( for ="mode" ) Interval mode:
14- td
15- select( id ="mode" , v-model ="mode" )
16- option( value ='last_duration' ) Last duration
17- option( value ='range' ) Date range
18- tr( v-if ="mode == 'last_duration'" )
19- th.pr-2
20- label( for ="duration" ) Show last:
21- td
22- select( id ="duration" , v-model ="duration" , @change ="valueChanged" )
23- option( :value ="15*60" ) 15min
24- option( :value ="30*60" ) 30min
25- option( :value ="60*60" ) 1h
26- option( :value ="2*60*60" ) 2h
27- option( :value ="4*60*60" ) 4h
28- option( :value ="6*60*60" ) 6h
29- option( :value ="12*60*60" ) 12h
30- option( :value ="24*60*60" ) 24h
31- tr( v-if ="mode == 'range'" )
32- th.pr-2 Range:
12+ td.pr-2
13+ label.col-form-label.col-form-label-sm Show last
14+ td( colspan =2 )
15+ .btn-group ( role ="group" )
16+ template( v-for ="(dur, idx) in durations" )
17+ input(
18+ type ="radio"
19+ :id ="'dur' + idx"
20+ :value ="dur.seconds"
21+ v-model ="duration"
22+ @change ="applyLastDuration"
23+ ) .d-none
24+ label( :for ="'dur' + idx" v-html ="dur.label" ) .btn.btn-light.btn-sm
25+
26+ tr
27+ td.pr-2
28+ label.col-form-label.col-form-label-sm Show from
3329 td
34- input( type ="date" , v-model ="start" )
35- input( type ="date" , v-model ="end" )
36- button(
37- class ="btn btn-outline-dark btn-sm" ,
30+ input.form-control.form-control-sm.d-inline-block.p-1 ( type ="date" , v-model ="start" , style ="height: auto; width: auto;" )
31+ label.col-form-label.col-form-label-sm.px-2 to
32+ input.form-control.form-control-sm.d-inline.p-1 ( type ="date" , v-model ="end" , style ="height: auto; width: auto" )
33+ td.text-right
34+ button.ml-2.btn.btn-outline-dark.btn-sm (
3835 type ="button" ,
39- :disabled ="mode == 'range' && ( invalidDaterange || emptyDaterange || daterangeTooLong) " ,
40- @click ="valueChanged "
41- ) Update
36+ :disabled ="invalidDaterange || emptyDaterange || daterangeTooLong" ,
37+ @click ="applyRange "
38+ ) Apply
4239
43- div( style ="text-align:right" v-if ="showUpdate && mode=='last_duration' " )
44- b-button.px-2 ( @click ="update ()" , variant ="outline-dark" , size ="sm" )
40+ div.text-muted.d-none.d-md-block ( style ="text-align:right" v-if ="showUpdate" )
41+ b-button.mt-2. px-2 ( @click ="refresh ()" , variant ="outline-dark" , size ="sm" , style = "opacity: 0.7 ")
4542 icon( name ="sync" )
4643 span.d-none.d-md-inline
47- | Update
48- div.mt-1 .small.text-muted ( v-if ="lastUpdate" )
44+ | Refresh
45+ div.mt-2 .small ( v-if ="lastUpdate" )
4946 | Last update: #[ time( :datetime ="lastUpdate.format()" ) {{lastUpdate | friendlytime}}]
5047</template >
5148
52- <style scoped lang="scss"></style >
49+ <style scoped lang="scss">
50+ .btn-group {
51+ input [type = ' radio' ]:checked + label {
52+ background-color : #aaa ;
53+ }
54+ }
55+ </style >
5356
5457<script lang="ts">
5558import moment from ' moment' ;
@@ -77,6 +80,18 @@ export default {
7780 start: null ,
7881 end: null ,
7982 lastUpdate: null ,
83+ durations: [
84+ { seconds: 0.25 * 60 * 60 , label: ' ¼h' },
85+ { seconds: 0.5 * 60 * 60 , label: ' ½h' },
86+ { seconds: 60 * 60 , label: ' 1h' },
87+ { seconds: 2 * 60 * 60 , label: ' 2h' },
88+ { seconds: 3 * 60 * 60 , label: ' 3h' },
89+ { seconds: 4 * 60 * 60 , label: ' 4h' },
90+ { seconds: 6 * 60 * 60 , label: ' 6h' },
91+ { seconds: 12 * 60 * 60 , label: ' 12h' },
92+ { seconds: 24 * 60 * 60 , label: ' 24h' },
93+ { seconds: 48 * 60 * 60 , label: ' 48h' },
94+ ],
8095 };
8196 },
8297 computed: {
@@ -103,13 +118,13 @@ export default {
103118 this .duration = this .defaultDuration ;
104119 this .valueChanged ();
105120
106- // We want our lastUpdated text to update every ~3s
121+ // We want our lastUpdated text to update every ~500ms
107122 // We can do this by setting it to null and then the previous value.
108123 this .lastUpdateTimer = setInterval (() => {
109124 const _lastUpdate = this .lastUpdate ;
110125 this .lastUpdate = null ;
111126 this .lastUpdate = _lastUpdate ;
112- }, 1000 );
127+ }, 500 );
113128 },
114129 beforeDestroy() {
115130 clearInterval (this .lastUpdateTimer );
@@ -124,12 +139,20 @@ export default {
124139 this .$emit (' input' , this .value );
125140 }
126141 },
127- update() {
128- if (this .mode == ' last_duration' ) {
129- this .mode = ' ' ; // remove cache on v-model, see explanation: https://github.com/ActivityWatch/aw-webui/pull/344/files#r892982094
130- this .mode = ' last_duration' ;
131- this .valueChanged ();
132- }
142+ refresh() {
143+ const tmpMode = this .mode ;
144+ this .mode = ' ' ;
145+ this .mode = tmpMode ;
146+ this .valueChanged ();
147+ },
148+ applyRange() {
149+ this .mode = ' range' ;
150+ this .duration = 0 ;
151+ this .valueChanged ();
152+ },
153+ applyLastDuration() {
154+ this .mode = ' last_duration' ;
155+ this .valueChanged ();
133156 },
134157 },
135158};
0 commit comments