Skip to content

Commit

Permalink
feat(timeline): swimlanes, duration filter, and filter desc to timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
kenbailey committed Jan 2, 2024
1 parent 845b12f commit 0d15764
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 3 deletions.
28 changes: 28 additions & 0 deletions src/util/swimlane.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import moment from 'moment';

Check warning on line 1 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / lint (20.x)

'moment' is defined but never used

Check warning on line 1 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / Build (node-16)

'moment' is defined but never used

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import moment.
import { seconds_to_duration } from './time';

Check warning on line 2 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / lint (20.x)

'seconds_to_duration' is defined but never used

Check warning on line 2 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / Build (node-16)

'seconds_to_duration' is defined but never used

Check notice

Code scanning / CodeQL

Unused variable, import, function or class Note

Unused import seconds_to_duration.
import DOMPurify from 'dompurify';
import _ from 'lodash';

Check warning on line 4 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / lint (20.x)

'_' is defined but never used

Check warning on line 4 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / Build (node-16)

'_' is defined but never used

const sanitize = DOMPurify.sanitize;

export function getSwimlane(bucket, color, groupBy, e) {
// WARNING: XSS risk, make sure to sanitize properly
// FIXME: Not actually tested against XSS attacks, implementation needs to be verified in tests.
let subgroup = 'unknown';

if (groupBy == 'category') {
subgroup = sanitize(color);
} else if (groupBy == 'bucketType') {
if (bucket.type == 'currentwindow') {
subgroup = sanitize(e.data.app);
} else if (bucket.type == 'web.tab.current') {
subgroup = sanitize((new URL(e.data.url)).hostname.replace('www.',''));

Check warning on line 19 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / lint (20.x)

Replace `(new·URL(e.data.url)).hostname.replace('www.',` with `new·URL(e.data.url).hostname.replace('www.',·`

Check warning on line 19 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / Build (node-16)

Replace `(new·URL(e.data.url)).hostname.replace('www.',` with `new·URL(e.data.url).hostname.replace('www.',·`
} else if (bucket.type.startsWith('app.editor')) {
subgroup = sanitize(e.data.language);
} else if (bucket.type.startsWith('general.stopwatch')) {
subgroup = sanitize(e.data.label);
}

Check warning on line 24 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / lint (20.x)

Delete `·`

Check warning on line 24 in src/util/swimlane.js

View workflow job for this annotation

GitHub Actions / Build (node-16)

Delete `·`
}

return subgroup;
}
60 changes: 58 additions & 2 deletions src/views/Timeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,15 @@ div
// blocks
div.d-inline-block.border.rounded.p-2.mr-2
| Events shown: {{ num_events }}
div.d-inline-block.border.rounded.p-2.mr-2
| Swimlanes:
select(v-model="swimlane")
option(value='null') None
option(value='category') Categories
option(value='bucketType') Bucket Specific
details.d-inline-block.bg-light.small.border.rounded.mr-2.px-2
summary.p-2
b Filters
b Filters: {{ filter_summary }}
div.p-2.bg-light
table
tr
Expand All @@ -26,12 +32,29 @@ div
select(v-model="filter_client")
option(:value='null') All
option(v-for="client in clients", :value="client") {{ client }}
tr
th.pt-2.pr-3
label Duration:
td
select(v-model="filter_duration")
option(value='null') All
option(value='2') 2+ secs
option(value='5') 5+ secs
option(value='10') 10+ secs
option(value='30') 30+ sec
option(value='60') 1+ mins
option(value='120') 2+ mins
option(value='180') 3+ mins
option(value='600') 10+ mins
option(value='1800') 30+ mins
option(value='3600') 1+ hrs
option(value='7200') 2+ hrs
div(style="float: right; color: #999").d-inline-block.pt-3
| Drag to pan and scroll to zoom

div(v-if="buckets !== null")
div(style="clear: both")
vis-timeline(:buckets="buckets", :showRowLabels='true', :queriedInterval="daterange")
vis-timeline(:buckets="buckets", :showRowLabels='true', :queriedInterval="daterange", :swimlane="swimlane")

aw-devonly(reason="Not ready for production, still experimenting")
aw-calendar(:buckets="buckets")
Expand All @@ -43,6 +66,7 @@ div
import _ from 'lodash';
import { useSettingsStore } from '~/stores/settings';
import { useBucketsStore } from '~/stores/buckets';
import { seconds_to_duration } from '~/util/time';
export default {
name: 'Timeline',
Expand All @@ -56,6 +80,8 @@ export default {
maxDuration: 31 * 24 * 60 * 60,
filter_hostname: null,
filter_client: null,
filter_duration: null,
swimlane: null,
};
},
computed: {
Expand All @@ -66,6 +92,23 @@ export default {
num_events() {
return _.sumBy(this.buckets, 'events.length');
},
filter_summary() {
let desc = [];

Check warning on line 96 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / lint (20.x)

'desc' is never reassigned. Use 'const' instead

Check warning on line 96 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / Build (node-16)

'desc' is never reassigned. Use 'const' instead
if (this.filter_hostname) {
desc.push(this.filter_hostname);
}
if (this.filter_client) {
desc.push(this.filter_client);
}
if (this.filter_duration > 0) {
desc.push(seconds_to_duration(this.filter_duration));
}

Check warning on line 105 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / lint (20.x)

Delete `·`

Check warning on line 105 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / Build (node-16)

Delete `·`
if (desc.length > 0) {
return desc.join(", ");

Check warning on line 108 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / lint (20.x)

Replace `",·"` with `',·'`

Check warning on line 108 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / Build (node-16)

Replace `",·"` with `',·'`
}
return "none"

Check warning on line 110 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / lint (20.x)

Replace `"none"` with `'none';`

Check warning on line 110 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / Build (node-16)

Replace `"none"` with `'none';`
}

Check warning on line 111 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / lint (20.x)

Insert `,`

Check warning on line 111 in src/views/Timeline.vue

View workflow job for this annotation

GitHub Actions / Build (node-16)

Insert `,`
},
watch: {
daterange() {
Expand All @@ -77,6 +120,12 @@ export default {
filter_client() {
this.getBuckets();
},
filter_duration() {
this.getBuckets();
},
swimlane() {
this.getBuckets();
},
},
methods: {
getBuckets: async function () {
Expand All @@ -103,6 +152,13 @@ export default {
if (this.filter_client) {
buckets = _.filter(buckets, b => b.client == this.filter_client);
}
if (this.filter_duration > 0) {
for (const bucket of buckets) {
bucket.events = _.filter(bucket.events, e => e.duration >= this.filter_duration);
}
}
this.buckets = buckets;
},
},
Expand Down
8 changes: 7 additions & 1 deletion src/visualizations/VisTimeline.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import moment from 'moment';
import Color from 'color';
import { buildTooltip } from '../util/tooltip.js';
import { getColorFromString, getTitleAttr } from '../util/color';
import { getSwimlane } from '../util/swimlane.js';
import { Timeline } from 'vis-timeline/esnext';
import 'vis-timeline/styles/vis-timeline-graph2d.css';
Expand All @@ -54,6 +55,7 @@ export default {
showRowLabels: { type: Boolean },
queriedInterval: { type: Array },
showQueriedInterval: { type: Boolean },
swimlane: { type: String },
},
data() {
return {
Expand Down Expand Up @@ -110,13 +112,15 @@ export default {
}
events.sort((a, b) => a.timestamp.valueOf() - b.timestamp.valueOf());
_.each(events, e => {
let color = getColorFromString(getTitleAttr(bucket, e));
data.push([
bucket.id,
getTitleAttr(bucket, e),
buildTooltip(bucket, e),
new Date(e.timestamp),
new Date(moment(e.timestamp).add(e.duration, 'seconds').valueOf()),
getColorFromString(getTitleAttr(bucket, e)),
color,
getSwimlane(bucket, color, this.swimlane, e),
e,
]);
});
Expand Down Expand Up @@ -223,6 +227,7 @@ export default {
start: moment(row[3]),
end: moment(row[4]),
style: `background-color: ${bgColor}; border-color: ${borderColor}`,
subgroup: row[6],
};
});
Expand All @@ -245,6 +250,7 @@ export default {
start: this.queriedInterval[0],
end: this.queriedInterval[1],
style: 'background-color: #aaa; height: 10px',
subgroup: ``,
});
}
Expand Down

1 comment on commit 0d15764

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are screenshots of this commit:

Screenshots using aw-server v0.12.3b11 (click to expand)

Screenshots using aw-server-rust master (click to expand)

Screenshots using aw-server-rust v0.12.3b11 (click to expand)

Please sign in to comment.