Merge pull request #3416 from gradido/admin_fix_resubmission

fix(admin): fix resubmission
This commit is contained in:
einhornimmond 2025-01-15 07:59:01 +01:00 committed by GitHub
commit f1d9dabbb3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 56 additions and 28 deletions

View File

@ -53,6 +53,7 @@
"vue-apollo": "3.1.2",
"vue-i18n": "9.13.1",
"vue-router": "4.4.0",
"vue3-datepicker": "^0.4.0",
"vuex": "4.1.0",
"vuex-persistedstate": "4.1.0"
},

View File

@ -9,11 +9,11 @@
</BFormGroup>
<BFormGroup v-if="showResubmissionDate">
<div class="d-flex my-2">
<BFormInput v-model="resubmissionDate" type="date" :min="now" class="w-25 me-2" />
<time-picker v-model="resubmissionTime" />
<Datepicker v-model="resubmissionDate" :lower-limit="now" class="form-control" />
<time-picker v-model="resubmissionTime" class="ms-2" />
</div>
</BFormGroup>
<BTabs v-model="tabindex" content-class="mt-3" data-test="message-type-tabs">
<BTabs v-model="tabindex" class="mt-3" content-class="mt-3" data-test="message-type-tabs">
<BTab active>
<template #title>
<span id="message-tab-title">{{ $t('moderator.message') }}</span>
@ -83,11 +83,11 @@ import { ref, computed } from 'vue'
import { useMutation } from '@vue/apollo-composable'
import { useI18n } from 'vue-i18n'
import Datepicker from 'vue3-datepicker'
import TimePicker from '@/components/input/TimePicker'
import { adminCreateContributionMessage } from '@/graphql/adminCreateContributionMessage'
import { adminUpdateContribution } from '@/graphql/adminUpdateContribution'
import { useAppToast } from '@/composables/useToast'
import { useDateFormatter } from '@/composables/useDateFormatter'
const props = defineProps({
contributionId: {
@ -118,8 +118,6 @@ const emit = defineEmits([
const { t } = useI18n()
const { toastError, toastSuccess } = useAppToast()
const { formatDateFromDateTime } = useDateFormatter()
const form = ref({
text: '',
memo: props.contributionMemo,
@ -129,7 +127,7 @@ const loading = ref(false)
const localInputResubmissionDate = props.inputResubmissionDate
? new Date(props.inputResubmissionDate)
: null
const resubmissionDate = ref(formatDateFromDateTime(props.inputResubmissionDate))
const resubmissionDate = ref(localInputResubmissionDate)
const resubmissionTime = ref(
localInputResubmissionDate
? localInputResubmissionDate.toLocaleTimeString('de-DE', {

View File

@ -16,7 +16,7 @@ describe('TimePicker', () => {
await input.setValue('23:45')
// Check if timeValue is updated
expect(wrapper.vm.timeValue).toBe('23:45')
expect(wrapper.vm.timeValue).toBe('23:45') // test for Vue 3 composition state directly, if possible
// Check if update:modelValue event is emitted with updated value
expect(wrapper.emitted('update:modelValue')).toBeTruthy()
@ -24,7 +24,11 @@ describe('TimePicker', () => {
})
it('validates and corrects time format on blur', async () => {
const wrapper = mount(TimePicker)
const wrapper = mount(TimePicker, {
props: {
modelValue: '99:99', // Set an invalid value initially
},
})
const input = wrapper.find('input[type="text"]')
@ -45,7 +49,11 @@ describe('TimePicker', () => {
})
it('checks handling of empty input', async () => {
const wrapper = mount(TimePicker)
const wrapper = mount(TimePicker, {
props: {
modelValue: '', // Set initial empty value
},
})
const input = wrapper.find('input[type="text"]')
// Simulate user input with empty string

View File

@ -12,8 +12,9 @@
</template>
<script>
import { ref, watch } from 'vue'
export default {
// Code written from chatGPT 3.5
name: 'TimePicker',
props: {
modelValue: {
@ -22,29 +23,42 @@ export default {
},
},
emits: ['update:modelValue'],
data() {
return {
timeValue: this.modelValue,
}
},
methods: {
updateValues(event) {
setup(props, { emit }) {
// reactive state
const timeValue = ref(props.modelValue)
// watch for prop changes
watch(
() => props.modelValue,
(newVal) => {
timeValue.value = newVal
},
)
const updateValues = (event) => {
// Allow only numbers and ":"
const inputValue = event.target.value.replace(/[^0-9:]/g, '')
this.timeValue = inputValue
this.$emit('update:modelValue', inputValue)
},
validateAndCorrect() {
let [hours, minutes] = this.timeValue.split(':')
timeValue.value = inputValue
emit('update:modelValue', inputValue)
}
const validateAndCorrect = () => {
let [hours, minutes] = timeValue.value.split(':')
// Validate hours and minutes
hours = Math.min(parseInt(hours) || 0, 23)
minutes = Math.min(parseInt(minutes) || 0, 59)
// Update the value with correct format
this.timeValue = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`
this.$emit('update:modelValue', this.timeValue)
},
timeValue.value = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}`
emit('update:modelValue', timeValue.value)
}
return {
timeValue,
updateValues,
validateAndCorrect,
}
},
}
</script>

View File

@ -57,7 +57,7 @@ export default defineConfig({
WALLET_AUTH_PATH: CONFIG.WALLET_AUTH_URL, // null,
WALLET_LOGIN_PATH: CONFIG.WALLET_LOGIN_URL, // null,
DEBUG_DISABLE_AUTH: CONFIG.DEBUG_DISABLE_AUTH, // null,
CONFIG_VERSION: CONFIG.CONFIG_VERSION, // null,
// CONFIG_VERSION: CONFIG.CONFIG_VERSION, // null,
}),
commonjs(),
],

View File

@ -3025,7 +3025,7 @@ data-view-byte-offset@^1.0.0:
es-errors "^1.3.0"
is-data-view "^1.0.1"
date-fns@^2.29.3:
date-fns@^2.22.1, date-fns@^2.29.3:
version "2.30.0"
resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.30.0.tgz#f367e644839ff57894ec6ac480de40cae4b0f4d0"
integrity sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==
@ -6882,6 +6882,13 @@ vue-router@4.4.0:
dependencies:
"@vue/devtools-api" "^6.5.1"
vue3-datepicker@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/vue3-datepicker/-/vue3-datepicker-0.4.0.tgz#d9493e801022062a89ba41e7927b391e5fe2e039"
integrity sha512-o0/y4yuZZc0DXYhiAlX8Znrkm/zvkeYuyV9PUt0UAvwxkno2jqMS388jVUa9Ns+a2s2pOAAybyXo5uQ9YAIwVw==
dependencies:
date-fns "^2.22.1"
vue@3.5.13:
version "3.5.13"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.13.tgz#9f760a1a982b09c0c04a867903fc339c9f29ec0a"