Show time correctly in the backup schedule UI (#12012)

This commit is contained in:
Abhisar Sinha 2025-12-17 19:17:28 +05:30 committed by GitHub
parent e08e66d66d
commit e9900aba23
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 143 additions and 35 deletions

View File

@ -99,7 +99,7 @@ export default {
default: false
},
dataSource: {
type: Object,
type: Array,
required: true
},
deleteFn: {
@ -128,6 +128,7 @@ export default {
dataIndex: 'intervaltype'
},
{
key: 'time',
title: this.$t('label.time'),
dataIndex: 'schedule'
},

View File

@ -35,16 +35,16 @@
v-model:value="form.intervaltype"
button-style="solid"
@change="handleChangeIntervalType">
<a-radio-button value="hourly">
<a-radio-button value="hourly" :disabled="isIntervalDisabled('hourly')">
{{ $t('label.hourly') }}
</a-radio-button>
<a-radio-button value="daily">
<a-radio-button value="daily" :disabled="isIntervalDisabled('daily')">
{{ $t('label.daily') }}
</a-radio-button>
<a-radio-button value="weekly">
<a-radio-button value="weekly" :disabled="isIntervalDisabled('weekly')">
{{ $t('label.weekly') }}
</a-radio-button>
<a-radio-button value="monthly">
<a-radio-button value="monthly" :disabled="isIntervalDisabled('monthly')">
{{ $t('label.monthly') }}
</a-radio-button>
</a-radio-group>
@ -54,6 +54,7 @@
<a-form-item :label="$t('label.time')" ref="time" name="time">
<a-input-number
style="width: 100%"
:disabled="isIntervalDisabled(form.intervaltype)"
v-model:value="form.time"
:placeholder="$t('label.minute.past.hour')"
:min="1"
@ -70,6 +71,7 @@
<a-time-picker
use12Hours
format="h:mm A"
:disabled="isIntervalDisabled(form.intervaltype)"
v-model:value="form.timeSelect"
style="width: 100%;" />
</a-form-item>
@ -79,6 +81,7 @@
<a-select
v-model:value="form['day-of-week']"
showSearch
:disabled="isIntervalDisabled(form.intervaltype)"
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
@ -94,6 +97,7 @@
<a-select
v-model:value="form['day-of-month']"
showSearch
:disabled="isIntervalDisabled(form.intervaltype)"
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
@ -180,6 +184,10 @@ export default {
type: Boolean,
default: false
},
dataSource: {
type: Array,
required: true
},
resource: {
type: Object,
required: true
@ -210,6 +218,38 @@ export default {
this.fetchTimeZone()
this.fetchBackupOffering()
},
mounted () {
if (this.form.intervaltype && this.isIntervalDisabled(this.form.intervaltype)) {
const nextAvailable = this.getNextAvailableIntervalType(this.form.intervaltype)
if (nextAvailable) {
this.form.intervaltype = nextAvailable
this.handleChangeIntervalType()
}
}
},
watch: {
dataSource: {
handler () {
if (this.form.intervaltype && this.getNextAvailableIntervalType && this.isIntervalDisabled(this.form.intervaltype)) {
const nextAvailable = this.getNextAvailableIntervalType(this.form.intervaltype)
if (nextAvailable) {
this.form.intervaltype = nextAvailable
this.handleChangeIntervalType()
}
}
},
deep: true
},
'form.intervaltype' (newVal) {
if (newVal && this.getNextAvailableIntervalType && this.isIntervalDisabled(newVal)) {
const nextAvailable = this.getNextAvailableIntervalType(newVal)
if (nextAvailable) {
this.form.intervaltype = nextAvailable
this.handleChangeIntervalType()
}
}
}
},
inject: ['refreshSchedule', 'closeSchedule'],
computed: {
isQuiesceVmSupported () {
@ -274,19 +314,39 @@ export default {
})
}
},
handleChangeIntervalType (e) {
switch (this.form.intervaltype) {
case 'weekly':
this.fetchDayOfWeek()
break
case 'monthly':
this.intervalValue = 'MONTHLY'
this.fetchDayOfMonth()
break
default:
break
handleChangeIntervalType () {
if (this.form.intervaltype === 'weekly') {
this.fetchDayOfWeek()
} else if (this.form.intervaltype === 'monthly') {
this.fetchDayOfMonth()
}
},
getNextAvailableIntervalType (currentIntervalType) {
const intervalTypes = ['hourly', 'daily', 'weekly', 'monthly']
const currentIndex = intervalTypes.indexOf(currentIntervalType ? currentIntervalType.toLowerCase() : '')
const startIndex = currentIndex >= 0 ? currentIndex : -1
for (let i = 1; i <= intervalTypes.length; i++) {
const nextIndex = (startIndex + i) % intervalTypes.length
const nextIntervalType = intervalTypes[nextIndex]
if (!this.isIntervalDisabled(nextIntervalType)) {
return nextIntervalType
}
}
return null
},
isIntervalDisabled (intervalType) {
intervalType = intervalType.toUpperCase()
if (this.dataSource?.length === 0) {
return false
}
const dataSource = this.dataSource.filter(item => item.intervaltype === intervalType)
if (dataSource && dataSource.length > 0) {
return true
}
return false
},
handleSubmit (e) {
if (this.actionLoading) return
this.formRef.value.validate().then(() => {
@ -294,7 +354,7 @@ export default {
const values = this.handleRemoveFields(formRaw)
const params = {}
params.virtualmachineid = this.resource.id
params.intervaltype = values.intervaltype
params.intervaltype = values.intervaltype.toUpperCase()
params.maxbackups = values.maxbackups
params.timezone = values.timezone
if (values.quiescevm) {

View File

@ -55,6 +55,7 @@
@cancel="closeModals">
<form-schedule
:resource="addFormResource"
:dataSource="dataSource"
:submitFn="handleAddBackupSchedule" />
</a-modal>
</div>
@ -90,7 +91,8 @@ export default {
return {
backupOffering: null,
showAddBackupSchedule: false,
localBackupOfferingId: this.backupOfferingId
localBackupOfferingId: this.backupOfferingId,
dataSource: []
}
},
provide () {

View File

@ -38,16 +38,16 @@
v-model:value="form.intervaltype"
buttonStyle="solid"
@change="handleChangeIntervalType">
<a-radio-button value="hourly" :disabled="handleVisibleInterval(0)">
<a-radio-button value="hourly" :disabled="isIntervalDisabled('hourly')">
{{ $t('label.hourly') }}
</a-radio-button>
<a-radio-button value="daily" :disabled="handleVisibleInterval(1)">
<a-radio-button value="daily" :disabled="isIntervalDisabled('daily')">
{{ $t('label.daily') }}
</a-radio-button>
<a-radio-button value="weekly" :disabled="handleVisibleInterval(2)">
<a-radio-button value="weekly" :disabled="isIntervalDisabled('weekly')">
{{ $t('label.weekly') }}
</a-radio-button>
<a-radio-button value="monthly" :disabled="handleVisibleInterval(3)">
<a-radio-button value="monthly" :disabled="isIntervalDisabled('monthly')">
{{ $t('label.monthly') }}
</a-radio-button>
</a-radio-group>
@ -60,6 +60,7 @@
:title="$t('label.minute.past.hour')">
<a-input-number
style="width: 100%"
:disabled="isIntervalDisabled(form.intervaltype)"
v-model:value="form.time"
:min="1"
:max="59"
@ -76,6 +77,7 @@
<a-time-picker
use12Hours
format="h:mm A"
:disabled="isIntervalDisabled(form.intervaltype)"
v-model:value="form.timeSelect"
style="width: 100%;" />
</a-form-item>
@ -85,6 +87,7 @@
<a-select
v-model:value="form['day-of-week']"
showSearch
:disabled="isIntervalDisabled(form.intervaltype)"
optionFilterProp="label"
:filterOption="(input, option) => {
return option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
@ -100,6 +103,7 @@
<a-select
v-model:value="form['day-of-month']"
showSearch
:disabled="isIntervalDisabled(form.intervaltype)"
optionFilterProp="value"
:filterOption="(input, option) => {
return option.value.toLowerCase().indexOf(input.toLowerCase()) >= 0
@ -311,6 +315,15 @@ export default {
this.volumeId = this.resource.id
this.fetchTimeZone()
},
mounted () {
if (this.form.intervaltype && this.isIntervalDisabled(this.form.intervaltype)) {
const nextAvailable = this.getNextAvailableIntervalType(this.form.intervaltype)
if (nextAvailable) {
this.form.intervaltype = nextAvailable
this.handleChangeIntervalType()
}
}
},
computed: {
formattedAdditionalZoneMessage () {
return `${this.$t('message.snapshot.additional.zones').replace('%x', this.resource.zonename)}`
@ -319,6 +332,20 @@ export default {
return isAdmin()
}
},
watch: {
dataSource: {
handler () {
if (this.form.intervaltype && this.getNextAvailableIntervalType && this.isIntervalDisabled(this.form.intervaltype)) {
const nextAvailable = this.getNextAvailableIntervalType(this.form.intervaltype)
if (nextAvailable) {
this.form.intervaltype = nextAvailable
this.handleChangeIntervalType()
}
}
},
deep: true
}
},
methods: {
initForm () {
this.formRef = ref()
@ -404,28 +431,46 @@ export default {
}
},
handleChangeIntervalType () {
switch (this.form.intervaltype) {
if (this.form.intervaltype === 'weekly') {
this.fetchDayOfWeek()
} else if (this.form.intervaltype === 'monthly') {
this.fetchDayOfMonth()
}
this.intervalValue = this.getIntervalValue(this.formintervaltype)
},
getIntervalValue (intervalType) {
switch (intervalType) {
case 'hourly':
this.intervalValue = 0
break
return 0
case 'daily':
this.intervalValue = 1
break
return 1
case 'weekly':
this.intervalValue = 2
this.fetchDayOfWeek()
break
return 2
case 'monthly':
this.intervalValue = 3
this.fetchDayOfMonth()
break
return 3
}
},
handleVisibleInterval (intervalType) {
getNextAvailableIntervalType (currentIntervalType) {
const intervalTypes = ['hourly', 'daily', 'weekly', 'monthly']
const currentIndex = intervalTypes.indexOf(currentIntervalType)
const startIndex = currentIndex >= 0 ? currentIndex : -1
for (let i = 1; i <= intervalTypes.length; i++) {
const nextIndex = (startIndex + i) % intervalTypes.length
const nextIntervalType = intervalTypes[nextIndex]
if (!this.isIntervalDisabled(nextIntervalType)) {
return nextIntervalType
}
}
return null
},
isIntervalDisabled (intervalType) {
const intervalValue = this.getIntervalValue(intervalType)
if (this.dataSource.length === 0) {
return false
}
const dataSource = this.dataSource.filter(item => item.intervaltype === intervalType)
const dataSource = this.dataSource.filter(item => item.intervaltype === intervalValue)
if (dataSource && dataSource.length > 0) {
return true
}