Skip to content

Commit e9900ab

Browse files
authored
Show time correctly in the backup schedule UI (#12012)
1 parent e08e66d commit e9900ab

File tree

4 files changed

+143
-35
lines changed

4 files changed

+143
-35
lines changed

ui/src/views/compute/backup/BackupSchedule.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export default {
9999
default: false
100100
},
101101
dataSource: {
102-
type: Object,
102+
type: Array,
103103
required: true
104104
},
105105
deleteFn: {
@@ -128,6 +128,7 @@ export default {
128128
dataIndex: 'intervaltype'
129129
},
130130
{
131+
key: 'time',
131132
title: this.$t('label.time'),
132133
dataIndex: 'schedule'
133134
},

ui/src/views/compute/backup/FormSchedule.vue

Lines changed: 76 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,16 +35,16 @@
3535
v-model:value="form.intervaltype"
3636
button-style="solid"
3737
@change="handleChangeIntervalType">
38-
<a-radio-button value="hourly">
38+
<a-radio-button value="hourly" :disabled="isIntervalDisabled('hourly')">
3939
{{ $t('label.hourly') }}
4040
</a-radio-button>
41-
<a-radio-button value="daily">
41+
<a-radio-button value="daily" :disabled="isIntervalDisabled('daily')">
4242
{{ $t('label.daily') }}
4343
</a-radio-button>
44-
<a-radio-button value="weekly">
44+
<a-radio-button value="weekly" :disabled="isIntervalDisabled('weekly')">
4545
{{ $t('label.weekly') }}
4646
</a-radio-button>
47-
<a-radio-button value="monthly">
47+
<a-radio-button value="monthly" :disabled="isIntervalDisabled('monthly')">
4848
{{ $t('label.monthly') }}
4949
</a-radio-button>
5050
</a-radio-group>
@@ -54,6 +54,7 @@
5454
<a-form-item :label="$t('label.time')" ref="time" name="time">
5555
<a-input-number
5656
style="width: 100%"
57+
:disabled="isIntervalDisabled(form.intervaltype)"
5758
v-model:value="form.time"
5859
:placeholder="$t('label.minute.past.hour')"
5960
:min="1"
@@ -70,6 +71,7 @@
7071
<a-time-picker
7172
use12Hours
7273
format="h:mm A"
74+
:disabled="isIntervalDisabled(form.intervaltype)"
7375
v-model:value="form.timeSelect"
7476
style="width: 100%;" />
7577
</a-form-item>
@@ -79,6 +81,7 @@
7981
<a-select
8082
v-model:value="form['day-of-week']"
8183
showSearch
84+
:disabled="isIntervalDisabled(form.intervaltype)"
8285
optionFilterProp="label"
8386
:filterOption="(input, option) => {
8487
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
@@ -94,6 +97,7 @@
9497
<a-select
9598
v-model:value="form['day-of-month']"
9699
showSearch
100+
:disabled="isIntervalDisabled(form.intervaltype)"
97101
optionFilterProp="label"
98102
:filterOption="(input, option) => {
99103
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
@@ -180,6 +184,10 @@ export default {
180184
type: Boolean,
181185
default: false
182186
},
187+
dataSource: {
188+
type: Array,
189+
required: true
190+
},
183191
resource: {
184192
type: Object,
185193
required: true
@@ -210,6 +218,38 @@ export default {
210218
this.fetchTimeZone()
211219
this.fetchBackupOffering()
212220
},
221+
mounted () {
222+
if (this.form.intervaltype && this.isIntervalDisabled(this.form.intervaltype)) {
223+
const nextAvailable = this.getNextAvailableIntervalType(this.form.intervaltype)
224+
if (nextAvailable) {
225+
this.form.intervaltype = nextAvailable
226+
this.handleChangeIntervalType()
227+
}
228+
}
229+
},
230+
watch: {
231+
dataSource: {
232+
handler () {
233+
if (this.form.intervaltype && this.getNextAvailableIntervalType && this.isIntervalDisabled(this.form.intervaltype)) {
234+
const nextAvailable = this.getNextAvailableIntervalType(this.form.intervaltype)
235+
if (nextAvailable) {
236+
this.form.intervaltype = nextAvailable
237+
this.handleChangeIntervalType()
238+
}
239+
}
240+
},
241+
deep: true
242+
},
243+
'form.intervaltype' (newVal) {
244+
if (newVal && this.getNextAvailableIntervalType && this.isIntervalDisabled(newVal)) {
245+
const nextAvailable = this.getNextAvailableIntervalType(newVal)
246+
if (nextAvailable) {
247+
this.form.intervaltype = nextAvailable
248+
this.handleChangeIntervalType()
249+
}
250+
}
251+
}
252+
},
213253
inject: ['refreshSchedule', 'closeSchedule'],
214254
computed: {
215255
isQuiesceVmSupported () {
@@ -274,18 +314,38 @@ export default {
274314
})
275315
}
276316
},
277-
handleChangeIntervalType (e) {
278-
switch (this.form.intervaltype) {
279-
case 'weekly':
280-
this.fetchDayOfWeek()
281-
break
282-
case 'monthly':
283-
this.intervalValue = 'MONTHLY'
284-
this.fetchDayOfMonth()
285-
break
286-
default:
287-
break
317+
handleChangeIntervalType () {
318+
if (this.form.intervaltype === 'weekly') {
319+
this.fetchDayOfWeek()
320+
} else if (this.form.intervaltype === 'monthly') {
321+
this.fetchDayOfMonth()
322+
}
323+
},
324+
getNextAvailableIntervalType (currentIntervalType) {
325+
const intervalTypes = ['hourly', 'daily', 'weekly', 'monthly']
326+
const currentIndex = intervalTypes.indexOf(currentIntervalType ? currentIntervalType.toLowerCase() : '')
327+
const startIndex = currentIndex >= 0 ? currentIndex : -1
328+
329+
for (let i = 1; i <= intervalTypes.length; i++) {
330+
const nextIndex = (startIndex + i) % intervalTypes.length
331+
const nextIntervalType = intervalTypes[nextIndex]
332+
333+
if (!this.isIntervalDisabled(nextIntervalType)) {
334+
return nextIntervalType
335+
}
336+
}
337+
return null
338+
},
339+
isIntervalDisabled (intervalType) {
340+
intervalType = intervalType.toUpperCase()
341+
if (this.dataSource?.length === 0) {
342+
return false
343+
}
344+
const dataSource = this.dataSource.filter(item => item.intervaltype === intervalType)
345+
if (dataSource && dataSource.length > 0) {
346+
return true
288347
}
348+
return false
289349
},
290350
handleSubmit (e) {
291351
if (this.actionLoading) return
@@ -294,7 +354,7 @@ export default {
294354
const values = this.handleRemoveFields(formRaw)
295355
const params = {}
296356
params.virtualmachineid = this.resource.id
297-
params.intervaltype = values.intervaltype
357+
params.intervaltype = values.intervaltype.toUpperCase()
298358
params.maxbackups = values.maxbackups
299359
params.timezone = values.timezone
300360
if (values.quiescevm) {

ui/src/views/compute/wizard/DeployInstanceBackupSelection.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
@cancel="closeModals">
5656
<form-schedule
5757
:resource="addFormResource"
58+
:dataSource="dataSource"
5859
:submitFn="handleAddBackupSchedule" />
5960
</a-modal>
6061
</div>
@@ -90,7 +91,8 @@ export default {
9091
return {
9192
backupOffering: null,
9293
showAddBackupSchedule: false,
93-
localBackupOfferingId: this.backupOfferingId
94+
localBackupOfferingId: this.backupOfferingId,
95+
dataSource: []
9496
}
9597
},
9698
provide () {

ui/src/views/storage/FormSchedule.vue

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,16 +38,16 @@
3838
v-model:value="form.intervaltype"
3939
buttonStyle="solid"
4040
@change="handleChangeIntervalType">
41-
<a-radio-button value="hourly" :disabled="handleVisibleInterval(0)">
41+
<a-radio-button value="hourly" :disabled="isIntervalDisabled('hourly')">
4242
{{ $t('label.hourly') }}
4343
</a-radio-button>
44-
<a-radio-button value="daily" :disabled="handleVisibleInterval(1)">
44+
<a-radio-button value="daily" :disabled="isIntervalDisabled('daily')">
4545
{{ $t('label.daily') }}
4646
</a-radio-button>
47-
<a-radio-button value="weekly" :disabled="handleVisibleInterval(2)">
47+
<a-radio-button value="weekly" :disabled="isIntervalDisabled('weekly')">
4848
{{ $t('label.weekly') }}
4949
</a-radio-button>
50-
<a-radio-button value="monthly" :disabled="handleVisibleInterval(3)">
50+
<a-radio-button value="monthly" :disabled="isIntervalDisabled('monthly')">
5151
{{ $t('label.monthly') }}
5252
</a-radio-button>
5353
</a-radio-group>
@@ -60,6 +60,7 @@
6060
:title="$t('label.minute.past.hour')">
6161
<a-input-number
6262
style="width: 100%"
63+
:disabled="isIntervalDisabled(form.intervaltype)"
6364
v-model:value="form.time"
6465
:min="1"
6566
:max="59"
@@ -76,6 +77,7 @@
7677
<a-time-picker
7778
use12Hours
7879
format="h:mm A"
80+
:disabled="isIntervalDisabled(form.intervaltype)"
7981
v-model:value="form.timeSelect"
8082
style="width: 100%;" />
8183
</a-form-item>
@@ -85,6 +87,7 @@
8587
<a-select
8688
v-model:value="form['day-of-week']"
8789
showSearch
90+
:disabled="isIntervalDisabled(form.intervaltype)"
8891
optionFilterProp="label"
8992
:filterOption="(input, option) => {
9093
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
@@ -100,6 +103,7 @@
100103
<a-select
101104
v-model:value="form['day-of-month']"
102105
showSearch
106+
:disabled="isIntervalDisabled(form.intervaltype)"
103107
optionFilterProp="value"
104108
:filterOption="(input, option) => {
105109
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
@@ -311,6 +315,15 @@ export default {
311315
this.volumeId = this.resource.id
312316
this.fetchTimeZone()
313317
},
318+
mounted () {
319+
if (this.form.intervaltype && this.isIntervalDisabled(this.form.intervaltype)) {
320+
const nextAvailable = this.getNextAvailableIntervalType(this.form.intervaltype)
321+
if (nextAvailable) {
322+
this.form.intervaltype = nextAvailable
323+
this.handleChangeIntervalType()
324+
}
325+
}
326+
},
314327
computed: {
315328
formattedAdditionalZoneMessage () {
316329
return `${this.$t('message.snapshot.additional.zones').replace('%x', this.resource.zonename)}`
@@ -319,6 +332,20 @@ export default {
319332
return isAdmin()
320333
}
321334
},
335+
watch: {
336+
dataSource: {
337+
handler () {
338+
if (this.form.intervaltype && this.getNextAvailableIntervalType && this.isIntervalDisabled(this.form.intervaltype)) {
339+
const nextAvailable = this.getNextAvailableIntervalType(this.form.intervaltype)
340+
if (nextAvailable) {
341+
this.form.intervaltype = nextAvailable
342+
this.handleChangeIntervalType()
343+
}
344+
}
345+
},
346+
deep: true
347+
}
348+
},
322349
methods: {
323350
initForm () {
324351
this.formRef = ref()
@@ -404,28 +431,46 @@ export default {
404431
}
405432
},
406433
handleChangeIntervalType () {
407-
switch (this.form.intervaltype) {
434+
if (this.form.intervaltype === 'weekly') {
435+
this.fetchDayOfWeek()
436+
} else if (this.form.intervaltype === 'monthly') {
437+
this.fetchDayOfMonth()
438+
}
439+
this.intervalValue = this.getIntervalValue(this.formintervaltype)
440+
},
441+
getIntervalValue (intervalType) {
442+
switch (intervalType) {
408443
case 'hourly':
409-
this.intervalValue = 0
410-
break
444+
return 0
411445
case 'daily':
412-
this.intervalValue = 1
413-
break
446+
return 1
414447
case 'weekly':
415-
this.intervalValue = 2
416-
this.fetchDayOfWeek()
417-
break
448+
return 2
418449
case 'monthly':
419-
this.intervalValue = 3
420-
this.fetchDayOfMonth()
421-
break
450+
return 3
451+
}
452+
},
453+
getNextAvailableIntervalType (currentIntervalType) {
454+
const intervalTypes = ['hourly', 'daily', 'weekly', 'monthly']
455+
const currentIndex = intervalTypes.indexOf(currentIntervalType)
456+
const startIndex = currentIndex >= 0 ? currentIndex : -1
457+
458+
for (let i = 1; i <= intervalTypes.length; i++) {
459+
const nextIndex = (startIndex + i) % intervalTypes.length
460+
const nextIntervalType = intervalTypes[nextIndex]
461+
462+
if (!this.isIntervalDisabled(nextIntervalType)) {
463+
return nextIntervalType
464+
}
422465
}
466+
return null
423467
},
424-
handleVisibleInterval (intervalType) {
468+
isIntervalDisabled (intervalType) {
469+
const intervalValue = this.getIntervalValue(intervalType)
425470
if (this.dataSource.length === 0) {
426471
return false
427472
}
428-
const dataSource = this.dataSource.filter(item => item.intervaltype === intervalType)
473+
const dataSource = this.dataSource.filter(item => item.intervaltype === intervalValue)
429474
if (dataSource && dataSource.length > 0) {
430475
return true
431476
}

0 commit comments

Comments
 (0)