Skip to content

Commit 94541c7

Browse files
committed
[ui] Schedule GitHub and GitLab tasks
Adds the option to schedule tasks to fetch GitHub and GitLab issues and pull requests.
1 parent f5722fc commit 94541c7

File tree

2 files changed

+202
-75
lines changed

2 files changed

+202
-75
lines changed

ui/src/components/TaskList/FormDialog.vue

Lines changed: 198 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -10,110 +10,235 @@
1010
v-bind="activatorProps"
1111
></v-btn>
1212
</template>
13-
1413
<v-card title="Schedule task">
15-
<v-card-text class="mt-4">
16-
<v-row dense>
17-
<v-col cols="6">
18-
<v-select
19-
v-model="formData.task_args.datasource_type"
20-
:items="['git']"
21-
color="primary"
22-
label="Backend"
23-
hide-details
24-
required
25-
/>
26-
</v-col>
27-
<v-col cols="6">
14+
<v-form ref="form" class="pa-6 pt-4">
15+
<fieldset>
16+
<legend class="text-subtitle-2 mb-3">Fetch data from a repository</legend>
17+
<div class="input-grid">
2818
<v-select
29-
v-model="formData.task_args.datasource_category"
30-
:items="['commit']"
31-
color="primary"
32-
label="Category"
33-
hide-details
34-
required
35-
/>
36-
</v-col>
37-
</v-row>
38-
<v-row>
39-
<v-col cols="12">
40-
<v-text-field
41-
v-model="formData.task_args.backend_args.uri"
19+
v-model="formData.datasourceType"
20+
:items="backends"
21+
item-title="backend"
4222
color="primary"
43-
label="URI"
44-
hide-details
45-
required
46-
/>
47-
</v-col>
48-
</v-row>
49-
<v-row>
50-
<v-col cols="6">
51-
<v-radio-group
52-
v-model="formData.scheduler.job_interval"
53-
density="comfortable"
54-
size="small"
23+
density="compact"
5524
>
56-
<template #label>
57-
<span class="text-subtitle-2">Interval</span>
25+
<template #selection="{ item }">
26+
<v-icon size="small" start>
27+
{{ 'mdi-' + item.title.toLowerCase() }}
28+
</v-icon>
29+
{{ item.title }}
30+
</template>
31+
<template #item="{ props, item }">
32+
<v-list-item
33+
v-bind="props"
34+
:prepend-icon="`mdi-${item.title.toLowerCase()}`"
35+
density="comfortable"
36+
nav
37+
/>
5838
</template>
59-
<v-radio :value="86400" label="Every day"></v-radio>
60-
<v-radio :value="604800" label="Every week"></v-radio>
61-
<v-radio value="custom" label="Custom"></v-radio>
62-
</v-radio-group>
39+
</v-select>
6340
<v-text-field
64-
v-model="customInterval"
65-
class="ml-8"
66-
label="Every"
67-
type="number"
68-
suffix="seconds"
69-
hide-details
70-
required
71-
>
72-
</v-text-field>
73-
</v-col>
74-
</v-row>
75-
</v-card-text>
76-
77-
<v-card-actions class="pt-0 pb-4 pr-4">
41+
v-model="formData.uri"
42+
label="Repository URL"
43+
color="primary"
44+
density="compact"
45+
:rules="rules.required"
46+
/>
47+
</div>
48+
</fieldset>
49+
<fieldset class="mt-2">
50+
<legend class="text-subtitle-2 mb-2">Select the data that you want to analyze</legend>
51+
<v-checkbox
52+
v-for="(category, index) in categories"
53+
v-model="formData.categories"
54+
:key="formData.datasourceType + category.value"
55+
:label="category.text"
56+
:value="category.value"
57+
color="primary"
58+
density="comfortable"
59+
:hide-details="index !== categories.length - 1"
60+
:rules="rules.category"
61+
/>
62+
</fieldset>
63+
<fieldset class="mt-2">
64+
<legend class="text-subtitle-2 mb-2">Schedule interval</legend>
65+
<v-radio-group
66+
v-model="formData.interval"
67+
color="primary"
68+
density="comfortable"
69+
hide-details
70+
>
71+
<v-radio :value="86400" label="Every day"></v-radio>
72+
<v-radio :value="604800" label="Every week"></v-radio>
73+
<v-radio value="custom" label="Custom"></v-radio>
74+
</v-radio-group>
75+
<v-row>
76+
<v-col cols="6">
77+
<v-text-field
78+
v-model="customInterval"
79+
class="mt-2 ml-8"
80+
color="primary"
81+
density="compact"
82+
hide-details="auto"
83+
label="Every"
84+
type="number"
85+
:rules="rules.customInterval"
86+
>
87+
<template #append>
88+
<span class="text-medium-emphasis">seconds</span>
89+
</template>
90+
</v-text-field>
91+
</v-col>
92+
</v-row>
93+
</fieldset>
94+
</v-form>
95+
<v-card-actions class="pt-0 pb-4 pr-6">
7896
<v-spacer></v-spacer>
79-
<v-btn text="Cancel" variant="plain" @click="isOpen = false"></v-btn>
97+
<v-btn text="Cancel" variant="plain" @click="closeModal"></v-btn>
8098
<v-btn color="primary" text="Save" variant="flat" @click="onSave"></v-btn>
8199
</v-card-actions>
82100
</v-card>
83101
</v-dialog>
84102
</template>
85103
<script>
104+
105+
const defaultData = {
106+
datasourceType: 'Git',
107+
categories: ['commit'],
108+
uri: '',
109+
interval: 604800
110+
}
111+
86112
export default {
87113
name: 'FormDialog',
88114
emits: ['create'],
89115
data() {
90116
return {
91117
isOpen: false,
92-
formData: {
118+
formData: { ...defaultData },
119+
customInterval: '',
120+
backends: [
121+
{
122+
backend: 'Git',
123+
categories: [{ text: 'Commits', value: 'commit' }]
124+
},
125+
{
126+
backend: 'GitHub',
127+
categories: [
128+
{ text: 'Issues', value: 'issue' },
129+
{ text: 'Pull Requests', value: 'prs' }
130+
]
131+
},
132+
{
133+
backend: 'GitLab',
134+
categories: [
135+
{ text: 'Issues', value: 'issue' },
136+
{ text: 'Merge Requests', value: 'merge' }
137+
]
138+
}
139+
],
140+
rules: {
141+
required: [
142+
(value) => {
143+
if (value) return true
144+
145+
return 'This field is required.'
146+
}
147+
],
148+
category: [
149+
(value) => {
150+
if (value.length > 0) return true
151+
return 'Select at least one category.'
152+
}
153+
],
154+
customInterval: [
155+
(value) => {
156+
if (this.formData.interval == 'custom' && !value) return 'Enter an interval.'
157+
return true
158+
}
159+
]
160+
}
161+
}
162+
},
163+
computed: {
164+
categories() {
165+
return this.backends.find((item) => item.backend === this.formData.datasourceType).categories
166+
},
167+
emitData() {
168+
return this.formData.categories.map((category) => ({
93169
type: 'eventizer',
94170
task_args: {
95-
datasource_type: 'git',
96-
datasource_category: 'commit',
171+
datasource_type: this.formData.datasourceType.toLowerCase(),
172+
datasource_category: category,
97173
backend_args: {
98-
uri: ''
99-
}
174+
uri: this.formData.uri
175+
},
100176
},
101177
scheduler: {
102-
job_interval: 604800,
103-
job_max_retries: 1
178+
job_interval: this.formData.interval
104179
}
105-
},
106-
customInterval: ''
180+
}))
107181
}
108182
},
109183
methods: {
110-
onSave() {
111-
if (this.formData.scheduler.job_interval === 'custom') {
112-
this.formData.scheduler.job_interval = this.customInterval
184+
async onSave() {
185+
const { valid } = await this.$refs.form.validate()
186+
187+
if (!valid) return
188+
189+
if (this.formData.interval === 'custom') {
190+
this.formData.interval = this.customInterval
113191
}
114-
this.$emit('create', this.formData)
192+
193+
this.$emit('create', this.emitData)
194+
this.closeModal()
195+
},
196+
closeModal() {
115197
this.isOpen = false
198+
this.resetForm()
199+
},
200+
resetForm() {
201+
this.formData = { ...defaultData }
202+
}
203+
},
204+
watch: {
205+
'formData.backend'() {
206+
Object.assign(this.formData, { categories: [] })
116207
}
117208
}
118209
}
119210
</script>
211+
<style lang="scss" scoped>
212+
.input-grid {
213+
display: grid;
214+
grid-template-columns: 0.7fr 2fr;
215+
216+
:deep(.v-select) .v-field {
217+
border-radius: 4px 0 0 4px;
218+
}
219+
220+
:deep(.v-input:not(.v-select)) .v-field {
221+
border-radius: 0 4px 4px 0;
222+
223+
&:not(.v-field--focused) .v-field__outline__start {
224+
border-inline-start-width: 0;
225+
}
226+
}
227+
}
228+
229+
.v-list-item--rounded {
230+
border-radius: 0;
231+
232+
:deep(.v-list-item__spacer) {
233+
width: 12px;
234+
}
235+
}
236+
237+
fieldset {
238+
border: 0;
239+
}
240+
241+
.v-input--density-comfortable {
242+
--v-input-control-height: 36px;
243+
}
244+
</style>

ui/src/views/Task/ListView.vue

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,12 +52,14 @@ export default {
5252
methods: {
5353
async createTask(formData) {
5454
try {
55-
const response = await API.scheduler.create(formData)
55+
const responses = await Promise.all(formData.map((task) => API.scheduler.create(task)))
56+
5657
Object.assign(this.snackbar, {
5758
open: true,
5859
color: 'success',
59-
text: response.data.message
60+
text: responses.map((response) => response.data.message).join(', ')
6061
})
62+
6163
this.fetchTasks(this.currentPage)
6264
} catch (error) {
6365
Object.assign(this.snackbar, {

0 commit comments

Comments
 (0)