-
-
Notifications
You must be signed in to change notification settings - Fork 107
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #233 from ActivityWatch/dev/customizable-views
- Loading branch information
Showing
15 changed files
with
399 additions
and
404 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
const defaultViews = [ | ||
{ | ||
id: 'summary', | ||
name: 'Summary', | ||
elements: [ | ||
{ type: 'top_apps', size: 3 }, | ||
{ type: 'top_titles', size: 3 }, | ||
{ type: 'top_domains', size: 3 }, | ||
{ type: 'top_categories', size: 3 }, | ||
{ type: 'category_tree', size: 3 }, | ||
{ type: 'category_sunburst', size: 3 }, | ||
], | ||
}, | ||
{ | ||
id: 'window', | ||
name: 'Window', | ||
elements: [ | ||
{ type: 'top_apps', size: 3 }, | ||
{ type: 'top_titles', size: 3 }, | ||
], | ||
}, | ||
{ | ||
id: 'browser', | ||
name: 'Browser', | ||
elements: [ | ||
{ type: 'top_domains', size: 3 }, | ||
{ type: 'top_urls', size: 3 }, | ||
], | ||
}, | ||
{ | ||
id: 'editor', | ||
name: 'Editor', | ||
elements: [ | ||
{ type: 'top_editor_files', size: 3 }, | ||
{ type: 'top_editor_projects', size: 3 }, | ||
{ type: 'top_editor_languages', size: 3 }, | ||
], | ||
}, | ||
]; | ||
|
||
// initial state | ||
const _state = { | ||
views: [], | ||
}; | ||
|
||
// getters | ||
const getters = {}; | ||
|
||
// actions | ||
const actions = { | ||
async load({ commit }) { | ||
commit('loadViews'); | ||
}, | ||
async save({ state, commit }) { | ||
localStorage.views = JSON.stringify(state.views); | ||
// After save, reload views | ||
commit('loadViews'); | ||
}, | ||
}; | ||
|
||
// mutations | ||
const mutations = { | ||
loadViews(state) { | ||
const views_json = localStorage.views; | ||
if (views_json && views_json.length >= 1) { | ||
state.views = JSON.parse(views_json); | ||
} else { | ||
state.views = defaultViews; | ||
} | ||
console.log('Loaded views:', state.views); | ||
}, | ||
restoreDefaults(state) { | ||
state.views = defaultViews; | ||
}, | ||
addView(state, view) { | ||
state.views.push({ ...view, elements: [] }); | ||
}, | ||
removeView(state, { view_id }) { | ||
const idx = state.views.map(v => v.id).indexOf(view_id); | ||
console.log(idx); | ||
state.views.splice(idx, 1); | ||
}, | ||
editView(state, { view_id, el_id, type }) { | ||
console.log(view_id, el_id, type); | ||
console.log(state.views); | ||
state.views.find(v => v.id == view_id).elements[el_id].type = type; | ||
}, | ||
addVisualization(state, { view_id, type }) { | ||
state.views.find(v => v.id == view_id).elements.push({ type: type }); | ||
}, | ||
removeVisualization(state, { view_id, el_id }) { | ||
state.views.find(v => v.id == view_id).elements.splice(el_id, 1); | ||
}, | ||
}; | ||
|
||
export default { | ||
namespaced: true, | ||
state: _state, | ||
getters, | ||
actions, | ||
mutations, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import _ from 'lodash'; | ||
import moment from 'moment'; | ||
|
||
// TODO: Move somewhere else, possibly turn into a serverside transform | ||
export function split_by_hour_into_data(events) { | ||
if (events === undefined || events === null || events.length == 0) return []; | ||
const d = moment(events[0].timestamp).startOf('day'); | ||
return _.range(0, 24).map(h => { | ||
let duration = 0; | ||
const d_start = d.clone().hour(h); | ||
const d_end = d.clone().hour(h + 1); | ||
// This can be made faster by not checking every event per hour, but since number of events is small anyway this and this is a lot shorter and easier to read it doesn't really matter. | ||
events.map(e => { | ||
const e_start = moment(e.timestamp); | ||
const e_end = e_start.clone().add(e.duration, 'seconds'); | ||
if ( | ||
e_start.isBetween(d_start, d_end) || | ||
e_end.isBetween(d_start, d_end) || | ||
d_start.isBetween(e_start, e_end) | ||
) { | ||
if (d_start < e_start && e_end < d_end) { | ||
// If entire event is contained within the hour | ||
duration += e.duration; | ||
} else if (d_start < e_start) { | ||
// If start of event is within the hour, but not the end | ||
duration += (d_end - e_start) / 1000; | ||
} else if (e_end < d_end) { | ||
// If end of event is within the hour, but not the start | ||
duration += (e_end - d_start) / 1000; | ||
} else { | ||
// Happens if event covers entire hour and more | ||
duration += 3600; | ||
} | ||
} | ||
}); | ||
return duration / 60 / 60; | ||
}); | ||
} |
Oops, something went wrong.