Skip to content

Commit c97d9ba

Browse files
committed
feat(wip): added bucket merge tool
1 parent 03caaa0 commit c97d9ba

File tree

2 files changed

+132
-1
lines changed

2 files changed

+132
-1
lines changed

src/components/BucketMerge.vue

+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
<template lang="pug">
2+
div
3+
h3 Merge buckets
4+
p.small
5+
| Sometimes, you might want to merge the events of two buckets together into one.
6+
| This is commonly useful to address the case where your hostname might have changed,
7+
| creating two buckets for the same watcher and host, which you want to combine together again.
8+
9+
// TODO: select which buckets to merge
10+
b-row
11+
b-col
12+
h4 Bucket from
13+
b-form-select(v-model="bucket_from" :options="buckets" :disabled="buckets.length === 0")
14+
p.small
15+
| Select the bucket from which you want to merge the events.
16+
| This bucket will be deleted after the merge.
17+
p(v-if="events_from !== null")
18+
| Events: {{ events_from.length }}
19+
b-col
20+
h4 Bucket to
21+
b-form-select(v-model="bucket_to" :options="buckets" :disabled="buckets.length === 0")
22+
p.small
23+
| Select the bucket to which you want to merge the events.
24+
| This bucket will remain after the merge.
25+
p(v-if="events_to !== null")
26+
| Events: {{ events_to.length }}
27+
28+
// TODO: check for overlapping events
29+
div(v-if="overlappingEvents.length > 0")
30+
h3 Overlapping events
31+
p
32+
| The following events are overlapping:
33+
ul
34+
li(v-for="event in overlappingEvents")
35+
| {{ event.from.start }} - {{ event.from.end }} ({{ event.from.id }})
36+
| overlaps with
37+
| {{ event.to.start }} - {{ event.to.end }} ({{ event.to.id }})
38+
39+
// TODO: confirm dialog
40+
b-button(variant="success" :disabled="!validate" @click="merge()") Merge
41+
42+
// TODO: delete old bucket? (ask user to backup their db if they want to be able to restore after delete)
43+
</template>
44+
45+
<script lang="ts">
46+
import { getClient } from '~/util/awclient';
47+
48+
export default {
49+
name: 'aw-bucket-merge',
50+
data() {
51+
return {
52+
buckets: [],
53+
bucket_from: null,
54+
bucket_to: null,
55+
events_from: null,
56+
events_to: null,
57+
};
58+
},
59+
computed: {
60+
validate() {
61+
const set = this.bucket_from !== null && this.bucket_to !== null;
62+
const not_same = this.bucket_from !== this.bucket_to;
63+
const not_overlapping = this.overlappingEvents.length === 0;
64+
return set && not_same && not_overlapping;
65+
},
66+
overlappingEvents() {
67+
if (this.events_from === null || this.events_to === null) {
68+
return [];
69+
}
70+
// check for overlapping events
71+
const overlapping = [];
72+
console.log('events_from', this.events_from);
73+
console.log('events_to', this.events_to);
74+
for (const event_from of this.events_from) {
75+
event_from.start = new Date(event_from.timestamp);
76+
event_from.end = new Date(event_from.timestamp + event_from.duration);
77+
for (const event_to of this.events_to) {
78+
event_to.start = new Date(event_to.timestamp);
79+
event_to.end = new Date(event_to.timestamp + event_to.duration);
80+
if (event_from.start < event_to.end && event_from.end > event_to.start) {
81+
overlapping.push({ from: event_from, to: event_to });
82+
}
83+
}
84+
}
85+
if (overlapping.length >= 0) {
86+
console.warn('Overlapping events found', overlapping);
87+
}
88+
return overlapping;
89+
},
90+
},
91+
watch: {
92+
bucket_from: async function (new_bucket_id) {
93+
this.events_from = await this.getEvents(new_bucket_id);
94+
},
95+
bucket_to: async function (new_bucket_id) {
96+
this.events_to = await this.getEvents(new_bucket_id);
97+
},
98+
},
99+
mounted() {
100+
this.getBuckets();
101+
},
102+
methods: {
103+
merge: async function () {
104+
const client = getClient();
105+
const events = this.events_from;
106+
const bucket_id = this.bucket_to;
107+
const result = await client.createEvents(bucket_id, events);
108+
console.log('result', result);
109+
},
110+
getBuckets: async function () {
111+
const client = getClient();
112+
const buckets = await client.getBuckets();
113+
console.log('buckets', buckets);
114+
this.buckets = Object.keys(buckets).map(bucket_id => {
115+
return { value: bucket_id, text: bucket_id };
116+
});
117+
},
118+
getEvents: async function (bucket_id) {
119+
const client = getClient();
120+
return await client.getEvents(bucket_id);
121+
},
122+
},
123+
};
124+
</script>

src/views/Buckets.vue

+8-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ div
2626
icon(name="folder-open").d-none.d-md-inline-block
2727
| Open
2828
b-dropdown(variant="outline-secondary", size="sm", text="More")
29+
// FIXME: These also exist as almost-copies in the Bucket view, can maybe be shared/reused instead.
2930
b-dropdown-item(
3031
:href="$aw.baseURL + '/api/0/buckets/' + data.item.id + '/export'",
3132
:download="'aw-bucket-export-' + data.item.id + '.json'",
@@ -64,7 +65,7 @@ div
6465
b-alert(v-if="import_error" show variant="danger" dismissable)
6566
| {{ import_error }}
6667
b-form-file(v-model="import_file"
67-
placeholder="Choose a file or drop file here..."
68+
placeholder="Choose or drop a file here..."
6869
drop-placeholder="Drop file here...")
6970
// TODO: This spinner could be placed in a more suitable place
7071
div(v-if="import_file" class="spinner-border" role="status")
@@ -79,6 +80,9 @@ div
7980
icon(name="download")
8081
| Export all buckets as JSON
8182

83+
hr
84+
85+
aw-bucket-merge
8286
</template>
8387

8488
<style lang="scss">
@@ -116,6 +120,9 @@ import { useBucketsStore } from '~/stores/buckets';
116120
117121
export default {
118122
name: 'Buckets',
123+
components: {
124+
'aw-bucket-merge': () => import('~/components/BucketMerge.vue'),
125+
},
119126
data() {
120127
return {
121128
bucketsStore: useBucketsStore(),

0 commit comments

Comments
 (0)