fix(frontend): migration remaining fixes (#3356)

* fix(frontend): fix password update validation, cleanup code, fix pipe operator in i18n issue, fixes to redeem via code.

* fix(frontend): fix transaction links

* fix(frontend): revert changes in admin components file

* fix(frontend): linters fixes
This commit is contained in:
MateuszMichalowski 2024-08-19 10:11:17 +02:00 committed by GitHub
parent d61e69c2f1
commit 76e5994441
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 383 additions and 1269 deletions

View File

@ -15,9 +15,9 @@
<BTab active>
<template #title>
<span id="message-tab-title">{{ $t('moderator.message') }}</span>
<b-tooltip target="message-tab-title" triggers="hover">
<BTooltip target="message-tab-title" triggers="hover">
{{ $t('moderator.message-tooltip') }}
</b-tooltip>
</BTooltip>
</template>
<BFormTextarea
id="textarea"
@ -150,10 +150,6 @@ const disabled = computed(() => {
)
})
// const moderatorDisabled = computed(() => {
// return form.value.text === '' || loading.value || tabindex.value === 1
// })
const now = computed(() => new Date())
const { mutate: createContributionMessageMutation } = useMutation(adminCreateContributionMessage)
@ -167,15 +163,6 @@ const combineResubmissionDateAndTime = () => {
return formattedDate
}
// const utcResubmissionDateTime = () => {
// if (!resubmissionDate.value) return null
// const localResubmissionDateAndTime = combineResubmissionDateAndTime()
// return new Date(
// localResubmissionDateAndTime.getTime() +
// localResubmissionDateAndTime.getTimezoneOffset() * 60000,
// )
// }
const onSubmit = () => {
loading.value = true
let mutation
@ -242,8 +229,4 @@ const onReset = () => {
showResubmissionDate.value =
props.inputResubmissionDate !== undefined && props.inputResubmissionDate !== null
}
// const enableMemo = () => {
// tabindex.value = 1
// }
</script>

View File

@ -8,6 +8,7 @@ export {}
declare module 'vue' {
export interface GlobalComponents {
AmountAndNameRow: typeof import('./src/components/TransactionRows/AmountAndNameRow.vue')['default']
AppModal: typeof import('./src/components/AppModal.vue')['default']
AuthCarousel: typeof import('./src/components/Auth/AuthCarousel.vue')['default']
AuthFooter: typeof import('./src/components/Auth/AuthFooter.vue')['default']
AuthNavbar: typeof import('./src/components/Auth/AuthNavbar.vue')['default']
@ -31,12 +32,15 @@ declare module 'vue' {
BFormGroup: typeof import('bootstrap-vue-next')['BFormGroup']
BFormInput: typeof import('bootstrap-vue-next')['BFormInput']
BFormInvalidFeedback: typeof import('bootstrap-vue-next')['BFormInvalidFeedback']
BFormRadio: typeof import('bootstrap-vue-next')['BFormRadio']
BFormRadioGroup: typeof import('bootstrap-vue-next')['BFormRadioGroup']
BFormSelect: typeof import('bootstrap-vue-next')['BFormSelect']
BFormTextarea: typeof import('bootstrap-vue-next')['BFormTextarea']
BImg: typeof import('bootstrap-vue-next')['BImg']
BInputGroup: typeof import('bootstrap-vue-next')['BInputGroup']
BLink: typeof import('bootstrap-vue-next')['BLink']
BModal: typeof import('bootstrap-vue-next')['BModal']
BModalOrchestrator: typeof import('bootstrap-vue-next')['BModalOrchestrator']
BNav: typeof import('bootstrap-vue-next')['BNav']
BNavbar: typeof import('bootstrap-vue-next')['BNavbar']
BNavbarBrand: typeof import('bootstrap-vue-next')['BNavbarBrand']
@ -82,21 +86,30 @@ declare module 'vue' {
GdtTransactionList: typeof import('./src/components/GdtTransactionList.vue')['default']
IBiArrowDownCircle: typeof import('~icons/bi/arrow-down-circle')['default']
IBiArrowUpCircle: typeof import('~icons/bi/arrow-up-circle')['default']
IBiArrowUpShort: typeof import('~icons/bi/arrow-up-short')['default']
IBiBellFill: typeof import('~icons/bi/bell-fill')['default']
IBiCaretDownFill: typeof import('~icons/bi/caret-down-fill')['default']
IBiCash: typeof import('~icons/bi/cash')['default']
IBiChatDots: typeof import('~icons/bi/chat-dots')['default']
IBiCheck: typeof import('~icons/bi/check')['default']
IBiClipboard: typeof import('~icons/bi/clipboard')['default']
IBiClipboardPlus: typeof import('~icons/bi/clipboard-plus')['default']
IBiDropletHalf: typeof import('~icons/bi/droplet-half')['default']
IBiExclamationTriangle: typeof import('~icons/bi/exclamation-triangle')['default']
IBiEye: typeof import('~icons/bi/eye')['default']
IBiEyeSlash: typeof import('~icons/bi/eye-slash')['default']
IBiFacebook: typeof import('~icons/bi/facebook')['default']
IBiLayers: typeof import('~icons/bi/layers')['default']
IBiLink45deg: typeof import('~icons/bi/link45deg')['default']
IBiPencil: typeof import('~icons/bi/pencil')['default']
IBiPeople: typeof import('~icons/bi/people')['default']
IBiQuestion: typeof import('~icons/bi/question')['default']
IBiShieldCheck: typeof import('~icons/bi/shield-check')['default']
IBiThreeDots: typeof import('~icons/bi/three-dots')['default']
IBiThreeDotsVertical: typeof import('~icons/bi/three-dots-vertical')['default']
IBiTrash: typeof import('~icons/bi/trash')['default']
IBiTwitterX: typeof import('~icons/bi/twitter-x')['default']
IBiX: typeof import('~icons/bi/x')['default']
IBiXCircle: typeof import('~icons/bi/x-circle')['default']
IBiYoutube: typeof import('~icons/bi/youtube')['default']
InputAmount: typeof import('./src/components/Inputs/InputAmount.vue')['default']

View File

@ -73,10 +73,6 @@ export default {
height: 13px;
}
.text-color-gdd-yellow {
color: rgb(197 141 56);
}
.dropdown > .dropdown-toggle {
border-radius: 17px;
height: 50px;

View File

@ -333,3 +333,7 @@ a:hover,
background-color: transparent;
border: none;
}
.text-color-gdd-yellow {
color: rgb(197 141 56);
}

View File

@ -0,0 +1,86 @@
<template>
<Teleport to="body">
<div v-if="props.modelValue" class="modal-overlay" @click="closeModal">
<div class="modal-content" @click.stop>
<div class="modal-header">
<h3>{{ props.title }}</h3>
<button class="close-button" @click="closeModal">
<IBiX />
</button>
</div>
<div class="modal-body">
<slot></slot>
</div>
<div class="modal-footer">
<BButton v-if="okOnly" class="btn-success" @click="emits('on-ok')">
{{ $t('form.ok') }}
</BButton>
<slot v-else name="footer">
<BButton @click="closeModal">{{ $('form.close') }}</BButton>
</slot>
</div>
</div>
</div>
</Teleport>
</template>
<script setup>
const props = defineProps({
modelValue: Boolean,
title: {
type: String,
default: '',
},
okOnly: {
type: Boolean,
default: false,
},
})
const emits = defineEmits(['update:modelValue', 'on-ok'])
const closeModal = () => {
emits('update:modelValue', false)
}
</script>
<style scoped>
.modal-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgb(0 0 0 / 50%);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: white;
padding: 20px;
border-radius: 8px;
max-width: 500px;
width: 100%;
}
.modal-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.close-button {
background: none;
border: none;
font-size: 1.5rem;
cursor: pointer;
}
.modal-footer {
margin-top: 15px;
text-align: right;
}
</style>

View File

@ -16,7 +16,7 @@
</div>
</BCol>
<BCol class="col-12 col-md-12 col-lg-6 mt-4 mb-4 mt-lg-0 mb-lg-0">
<div class="text-center ml-3 ml-lg-0 text-lg-right pt-1">
<div class="d-flex align-items-center ml-3 ml-lg-0 text-lg-right pt-1">
{{ $t('followUs') }}
<BLink href="https://www.facebook.com/groups/Gradido/" target="_blank">
<!-- <b-icon-facebook class="ml-3 mr-3 c-grey" font-scale="1"></b-icon-facebook>-->

View File

@ -9,7 +9,7 @@
<BCollapse id="nav-collapse" is-nav>
<BNavbarNav class="ml-auto d-none d-lg-flex" right>
<BNavItem :to="register()" class="auth-navbar ml-lg-5">{{ $t('signup') }}</BNavItem>
<span class="d-none d-lg-block mt-1">{{ $t('math.pipe') }}</span>
<span class="d-none d-lg-block">{{ $t('|') }}</span>
<BNavItem :to="login()" class="auth-navbar">{{ $t('signin') }}</BNavItem>
</BNavbarNav>
</BCollapse>

View File

@ -3,7 +3,7 @@
<BNavbar class="navi">
<BNavbarNav>
<BNavItem :to="register()" class="auth-navbar">{{ $t('signup') }}</BNavItem>
<span class="mt-1">{{ $t('math.pipe') }}</span>
<span class="mt-1">{{ $t('|') }}</span>
<BNavItem :to="login()" class="auth-navbar">{{ $t('signin') }}</BNavItem>
</BNavbarNav>
</BNavbar>

View File

@ -12,7 +12,6 @@
<div>
<BButton class="p-4">
<IBiLink45deg />
<!-- <b-icon icon="link45deg"></b-icon>-->
</BButton>
</div>
</div>
@ -28,7 +27,6 @@
<div>
<BButton class="p-4">
<IBiLink45deg />
<!-- <b-icon icon="link45deg"></b-icon>-->
</BButton>
</div>
</div>

View File

@ -20,76 +20,6 @@
</div>
</div>
</template>
<!--<script>-->
<!--import { selectCommunities } from '@/graphql/queries'-->
<!--export default {-->
<!-- name: 'CommunitySwitch',-->
<!-- props: {-->
<!-- value: {-->
<!-- type: Object,-->
<!-- },-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- communities: [],-->
<!-- validCommunityIdentifier: false,-->
<!-- }-->
<!-- },-->
<!-- methods: {-->
<!-- updateCommunity(community) {-->
<!-- this.$emit('input', community)-->
<!-- },-->
<!-- setDefaultCommunity() {-->
<!-- // when we already get an identifier via url we choose this if the community exist-->
<!-- if (this.communityIdentifier && this.communities.length >= 1) {-->
<!-- const foundCommunity = this.communities.find((community) => {-->
<!-- if (-->
<!-- community.uuid === this.communityIdentifier ||-->
<!-- community.name === this.communityIdentifier-->
<!-- ) {-->
<!-- this.validCommunityIdentifier = true-->
<!-- return true-->
<!-- }-->
<!-- return false-->
<!-- })-->
<!-- if (foundCommunity) {-->
<!-- this.updateCommunity(foundCommunity)-->
<!-- return-->
<!-- }-->
<!-- this.toastError('invalid community identifier in url')-->
<!-- }-->
<!-- if (this.validCommunityIdentifier && !this.communityIdentifier) {-->
<!-- this.validCommunityIdentifier = false-->
<!-- }-->
<!-- // set default community, the only one which isn't foreign-->
<!-- // we assume it is only one entry with foreign = false-->
<!-- if (this.value.uuid === '' && this.communities.length) {-->
<!-- const foundCommunity = this.communities.find((community) => !community.foreign)-->
<!-- if (foundCommunity) {-->
<!-- this.updateCommunity(foundCommunity)-->
<!-- }-->
<!-- }-->
<!-- },-->
<!-- },-->
<!-- apollo: {-->
<!-- communities: {-->
<!-- query: selectCommunities,-->
<!-- },-->
<!-- },-->
<!-- computed: {-->
<!-- communityIdentifier() {-->
<!-- return this.$route.params && this.$route.params.communityIdentifier-->
<!-- },-->
<!-- },-->
<!-- updated() {-->
<!-- this.setDefaultCommunity()-->
<!-- },-->
<!-- mounted() {-->
<!-- this.setDefaultCommunity()-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, computed, watch, onMounted, onUpdated } from 'vue'
@ -113,7 +43,7 @@ const { toastError } = useAppToast()
const communities = ref([])
const validCommunityIdentifier = ref(false)
const { result, onResult } = useQuery(selectCommunities)
const { onResult } = useQuery(selectCommunities)
onResult(({ data }) => {
if (data) {

View File

@ -11,7 +11,7 @@
>
{{ $t('footer.copyright.link') }}
</a>
{{ $t('math.pipe') }}
{{ $t('|') }}
<a href="https://github.com/gradido/gradido/releases/latest" target="_blank">
{{ $t('footer.app_version', { version }) }}
</a>

View File

@ -29,7 +29,6 @@
<IBiCheck v-else-if="confirmedAt" />
<IBiQuestion v-else-if="status === 'IN_PROGRESS'" />
<IBiBellFill v-else />
<!-- <b-icon :icon="icon" :variant="variant"></b-icon>-->
</div>
<div class="small">
{{ $d(new Date(contributionDate), 'short') }}

View File

@ -6,8 +6,8 @@
<div>
<transaction-link
v-for="item in transactionLinks"
:key="item.id"
v-bind="item"
:key="item.id"
@reset-transaction-link-list="resetTransactionLinkList"
/>
<div class="mb-3">
@ -16,7 +16,7 @@
class="test-button-load-more"
block
variant="outline-primary"
@click="loadMoreLinks"
@click.stop="loadMoreLinks"
>
{{ buttonText }}
</BButton>

View File

@ -1,7 +1,6 @@
<template>
<div class="decayinformation-decay">
<div class="mb-3">
<!-- <b-icon icon="droplet-half" class="mr-2" />-->
<IBiDropletHalf class="mr-2" />
<b>{{ $t('decay.calculation_decay') }}</b>
</div>

View File

@ -3,7 +3,7 @@
<BRow>
<BCol cols="12">
<div class="text-center pb-3">
<b-icon icon="droplet-half" class="mr-2" />
<IBiDropletHalf class="mr-2" />
<b>{{ $t('decay.Starting_block_decay') }}</b>
</div>
</BCol>

View File

@ -25,7 +25,6 @@
<BRow class="mt-5 text-color-gdd-yellow h3">
<BCol cols="2" class="text-right">
<!-- <b-icon class="text-color-gdd-yellow" icon="droplet-half"></b-icon>-->
<IBiDropletHalf />
</BCol>
<BCol>{{ $t('advanced-calculation') }}</BCol>

View File

@ -130,131 +130,6 @@
</BRow>
</div>
</template>
<!--<script>-->
<!--import { SEND_TYPES } from '@/utils/sendTypes'-->
<!--import InputIdentifier from '@/components/Inputs/InputIdentifier'-->
<!--import InputAmount from '@/components/Inputs/InputAmount'-->
<!--import InputTextarea from '@/components/Inputs/InputTextarea'-->
<!--import CommunitySwitch from '@/components/CommunitySwitch.vue'-->
<!--import { user } from '@/graphql/queries'-->
<!--import CONFIG from '@/config'-->
<!--export default {-->
<!-- name: 'TransactionForm',-->
<!-- components: {-->
<!-- InputIdentifier,-->
<!-- InputAmount,-->
<!-- InputTextarea,-->
<!-- CommunitySwitch,-->
<!-- },-->
<!-- props: {-->
<!-- balance: { type: Number, default: 0 },-->
<!-- identifier: { type: String, default: '' },-->
<!-- amount: { type: Number, default: 0 },-->
<!-- memo: { type: String, default: '' },-->
<!-- selected: { type: String, default: 'send' },-->
<!-- targetCommunity: {-->
<!-- type: Object,-->
<!-- default: function () {-->
<!-- return { uuid: '', name: CONFIG.COMMUNITY_NAME }-->
<!-- },-->
<!-- },-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- form: {-->
<!-- identifier: this.identifier,-->
<!-- amount: this.amount ? String(this.amount) : '',-->
<!-- memo: this.memo,-->
<!-- targetCommunity: this.targetCommunity,-->
<!-- },-->
<!-- radioSelected: this.selected,-->
<!-- userName: '',-->
<!-- recipientCommunity: { uuid: '', name: '' },-->
<!-- }-->
<!-- },-->
<!-- methods: {-->
<!-- onValidation() {-->
<!-- this.$refs.formValidator.validate()-->
<!-- },-->
<!-- onSubmit() {-->
<!-- if (this.userIdentifier) this.form.identifier = this.userIdentifier.identifier-->
<!-- this.$emit('set-transaction', {-->
<!-- selected: this.radioSelected,-->
<!-- identifier: this.form.identifier,-->
<!-- amount: Number(this.form.amount.replace(',', '.')),-->
<!-- memo: this.form.memo,-->
<!-- userName: this.userName,-->
<!-- targetCommunity: this.form.targetCommunity,-->
<!-- })-->
<!-- },-->
<!-- onReset(event) {-->
<!-- event.preventDefault()-->
<!-- this.form.identifier = ''-->
<!-- this.form.amount = ''-->
<!-- this.form.memo = ''-->
<!-- this.form.targetCommunity = { uuid: '', name: COMMUNITY_NAME }-->
<!-- this.$refs.formValidator.validate()-->
<!-- this.$router.replace('/send')-->
<!-- },-->
<!-- },-->
<!-- apollo: {-->
<!-- UserName: {-->
<!-- query() {-->
<!-- return user-->
<!-- },-->
<!-- fetchPolicy: 'network-only',-->
<!-- variables() {-->
<!-- return this.userIdentifier-->
<!-- },-->
<!-- skip() {-->
<!-- return !this.userIdentifier-->
<!-- },-->
<!-- update({ user }) {-->
<!-- this.userName = `${user.firstName} ${user.lastName}`-->
<!-- },-->
<!-- error({ message }) {-->
<!-- this.toastError(message)-->
<!-- },-->
<!-- },-->
<!-- },-->
<!-- computed: {-->
<!-- disabled() {-->
<!-- if (-->
<!-- this.form.identifier.length > 5 &&-->
<!-- parseInt(this.form.amount) <= parseInt(this.balance) &&-->
<!-- this.form.memo.length > 5 &&-->
<!-- this.form.memo.length <= 255-->
<!-- ) {-->
<!-- return false-->
<!-- }-->
<!-- return true-->
<!-- },-->
<!-- isBalanceDisabled() {-->
<!-- return this.balance <= 0 ? 'disabled' : false-->
<!-- },-->
<!-- sendTypes() {-->
<!-- return SEND_TYPES-->
<!-- },-->
<!-- userIdentifier() {-->
<!-- if (-->
<!-- this.$route.params &&-->
<!-- this.$route.params.userIdentifier &&-->
<!-- this.$route.params.communityIdentifier-->
<!-- ) {-->
<!-- return {-->
<!-- identifier: this.$route.params.userIdentifier,-->
<!-- communityIdentifier: this.$route.params.communityIdentifier,-->
<!-- }-->
<!-- }-->
<!-- return null-->
<!-- },-->
<!-- },-->
<!-- mounted() {-->
<!-- if (this.form.identifier !== '') this.$refs.formValidator.validate()-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, computed, watch } from 'vue'
@ -292,7 +167,6 @@ const radioSelected = ref(props.selected)
const userName = ref('')
const recipientCommunity = ref({ uuid: '', name: '' })
// Use vee-validate's useForm
const { handleSubmit, resetForm, defineField } = useForm({
initialValues: {
identifier: props.identifier,
@ -354,13 +228,6 @@ function onReset(event) {
radioSelected.value = SEND_TYPES.send
router.replace('/send')
}
// Expose necessary methods and computed properties
// defineExpose({
// sendTypes: SEND_TYPES,
// handleSubmit: onSubmit,
// onReset,
// })
</script>
<style>

View File

@ -37,59 +37,7 @@
</BInputGroup>
</div>
</template>
<!--<script>-->
<!--export default {-->
<!-- name: 'InputAmount',-->
<!-- props: {-->
<!-- rules: {-->
<!-- type: Object,-->
<!-- default: () => {},-->
<!-- },-->
<!-- typ: { type: String, default: 'TransactionForm' },-->
<!-- name: { type: String, required: true, default: 'Amount' },-->
<!-- label: { type: String, required: true, default: 'Amount' },-->
<!-- placeholder: { type: String, required: true, default: 'Amount' },-->
<!-- value: { type: String, required: true },-->
<!-- balance: { type: Number, default: 0.0 },-->
<!-- disabled: { required: false, type: Boolean, default: false },-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- currentValue: this.value,-->
<!-- amountValue: 0.0,-->
<!-- amountFocused: false,-->
<!-- }-->
<!-- },-->
<!-- computed: {-->
<!-- errorMessages() {-->
<!-- return errorMessages-->
<!-- },-->
<!-- labelFor() {-->
<!-- return this.name + '-input-field'-->
<!-- },-->
<!-- },-->
<!-- watch: {-->
<!-- currentValue() {-->
<!-- this.$emit('input', this.currentValue)-->
<!-- },-->
<!-- value() {-->
<!-- if (this.value !== this.currentValue) this.currentValue = this.value-->
<!-- },-->
<!-- },-->
<!-- methods: {-->
<!-- normalizeAmount(isValid) {-->
<!-- this.amountFocused = false-->
<!-- if (!isValid) return-->
<!-- this.amountValue = this.currentValue.replace(',', '.')-->
<!-- this.currentValue = this.$n(this.amountValue, 'ungroupedDecimal')-->
<!-- },-->
<!-- },-->
<!-- mounted() {-->
<!-- if (this.value !== '') this.normalizeAmount(true)-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, computed, watch } from 'vue'
import { useField } from 'vee-validate'
@ -134,14 +82,7 @@ watch(
)
const normalizeAmount = (inputValue) => {
const oldValue = value.value
const amountPattern = /^\d+([,.]\d{1,2})?$/
amountFocused.value = false
// if (!meta.valid) return
// if (!amountPattern.test(inputValue)) {
// value.value = oldValue
// } else {
value.value = inputValue.replace(',', '.')
// }
}
</script>

View File

@ -1,34 +1,3 @@
<!--<template>-->
<!-- <validation-provider-->
<!-- tag="div"-->
<!-- :rules="rules"-->
<!-- :name="name"-->
<!-- v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"-->
<!-- >-->
<!-- <BFormGroup :label="label" :label-for="labelFor" data-test="input-email">-->
<!-- <BFormInput-->
<!-- v-model="currentValue"-->
<!-- v-bind="ariaInput"-->
<!-- data-test="input-email"-->
<!-- :id="labelFor"-->
<!-- :name="name"-->
<!-- :placeholder="placeholder"-->
<!-- type="email"-->
<!-- :state="validated ? valid : false"-->
<!-- trim-->
<!-- :class="$route.path === '/send' ? 'bg-248' : ''"-->
<!-- v-focus="emailFocused"-->
<!-- @focus="emailFocused = true"-->
<!-- @blur="normalizeEmail()"-->
<!-- :disabled="disabled"-->
<!-- autocomplete="off"-->
<!-- />-->
<!-- <BFormInvalidFeedback v-bind="ariaMsg">-->
<!-- {{ errors[0] }}-->
<!-- </BFormInvalidFeedback>-->
<!-- </BFormGroup>-->
<!-- </validation-provider>-->
<!--</template>-->
<template>
<div>
<BFormGroup :label="defaultTranslations.label" :label-for="labelFor" data-test="input-email">
@ -53,70 +22,12 @@
</BFormGroup>
</div>
</template>
<!--<script>-->
<!--export default {-->
<!-- name: 'InputEmail',-->
<!-- props: {-->
<!-- rules: {-->
<!-- default: () => {-->
<!-- return {-->
<!-- required: true,-->
<!-- email: true,-->
<!-- }-->
<!-- },-->
<!-- },-->
<!-- name: { type: String, required: true },-->
<!-- label: { type: String, required: true },-->
<!-- placeholder: { type: String, required: true },-->
<!-- modelValue: { type: String, required: true },-->
<!-- disabled: { type: Boolean, required: false, default: false },-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- currentValue: this.modelValue,-->
<!-- emailFocused: false,-->
<!-- }-->
<!-- },-->
<!-- computed: {-->
<!-- labelFor() {-->
<!-- return this.name + '-input-field'-->
<!-- },-->
<!-- },-->
<!-- watch: {-->
<!-- currentValue() {-->
<!-- this.$emit('input', this.currentValue)-->
<!-- },-->
<!-- modelValue() {-->
<!-- if (this.modelValue !== this.currentValue) {-->
<!-- this.currentValue = this.modelValue-->
<!-- }-->
<!-- this.$emit('onValidation')-->
<!-- },-->
<!-- },-->
<!-- methods: {-->
<!-- normalizeEmail() {-->
<!-- this.emailFocused = false-->
<!-- this.currentValue = this.currentValue.trim()-->
<!-- },-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, watch, computed, defineProps, defineEmits } from 'vue'
import { computed, defineProps, defineEmits } from 'vue'
import { useField } from 'vee-validate'
import { useI18n } from 'vue-i18n'
import * as yup from 'yup'
// rules: {
// type: [String, Object, Function],
// default: () => ({
// required: true,
// email: true,
// }),
// },
// Define props with default values
const props = defineProps({
name: {
type: String,
@ -138,26 +49,20 @@ const props = defineProps({
const emit = defineEmits(['onValidation'])
// Use the useField hook for validation
const { value, errorMessage, errors, validate, meta } = useField(() => props.name, 'required|email')
const { value, errorMessage, validate, meta } = useField(() => props.name, 'required|email')
const { t } = useI18n()
// const emailFocused = ref(false)
const defaultTranslations = computed(() => ({
label: props.label ?? t('form.email'),
placeholder: props.placeholder ?? t('form.email'),
}))
const normalizeEmail = (emailAddress) => {
// TODO trigger blur on bootstrap input
// emailFocused.value = false
value.value = emailAddress.trim()
validate()
}
// Computed properties for ARIA attributes and labelFor
const ariaInput = computed(() => ({
'aria-invalid': errorMessage ? 'true' : false,
'aria-describedby': `${props.name}-feedback`,

View File

@ -1,28 +1,4 @@
<template>
<!-- <div class="input-hour">-->
<!-- <validation-provider-->
<!-- tag="div"-->
<!-- :rules="rules"-->
<!-- :name="name"-->
<!-- v-slot="{ valid, validated, ariaInput }"-->
<!-- >-->
<!-- <b-form-group :label="label" :label-for="labelFor">-->
<!-- <b-form-input-->
<!-- v-model="currentValue"-->
<!-- v-bind="ariaInput"-->
<!-- :id="labelFor"-->
<!-- :name="name"-->
<!-- :placeholder="placeholder"-->
<!-- type="number"-->
<!-- :state="validated ? valid : false"-->
<!-- step="0.25"-->
<!-- min="0"-->
<!-- :max="validMaxTime"-->
<!-- class="bg-248"-->
<!-- ></b-form-input>-->
<!-- </b-form-group>-->
<!-- </validation-provider>-->
<!-- </div>-->
<div class="input-hour">
<BFormGroup :label="label" :label-for="labelFor">
<BFormInput
@ -44,41 +20,6 @@
</BFormGroup>
</div>
</template>
<!--<script>-->
<!--export default {-->
<!-- name: 'InputHour',-->
<!-- props: {-->
<!-- rules: {-->
<!-- type: Object,-->
<!-- default: () => {},-->
<!-- },-->
<!-- name: { type: String, required: true },-->
<!-- label: { type: String, required: true },-->
<!-- placeholder: { type: String, required: true },-->
<!-- value: { type: Number, required: true, default: 0 },-->
<!-- validMaxTime: { type: Number, required: true },-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- currentValue: 0,-->
<!-- }-->
<!-- },-->
<!-- computed: {-->
<!-- labelFor() {-->
<!-- return this.name + '-input-field'-->
<!-- },-->
<!-- },-->
<!-- watch: {-->
<!-- currentValue() {-->
<!-- this.$emit('input', Number(this.currentValue))-->
<!-- },-->
<!-- value() {-->
<!-- if (this.value !== this.currentValue) this.currentValue = this.value-->
<!-- this.$emit('updateAmount', this.currentValue)-->
<!-- },-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, computed, watch } from 'vue'

View File

@ -1,50 +1,3 @@
<!--<template>-->
<!-- <validation-provider-->
<!-- tag="div"-->
<!-- :rules="rules"-->
<!-- :name="name"-->
<!-- :bails="!props.showAllErrors"-->
<!-- :immediate="props.immediate"-->
<!-- v-slot="{ errors, valid, validated, ariaInput, ariaMsg }"-->
<!-- >-->
<!-- <BFormGroup :label="label" :label-for="labelFor">-->
<!-- <BInputGroup>-->
<!-- <BFormInput-->
<!-- v-model="currentValue"-->
<!-- v-bind="ariaInput"-->
<!-- :id="labelFor"-->
<!-- :name="name"-->
<!-- :placeholder="props.placeholder"-->
<!-- :type="showPassword ? 'text' : 'password'"-->
<!-- :state="validated ? valid : false"-->
<!-- data-test="password-input-field"-->
<!-- ></BFormInput>-->
<!-- <template #append>-->
<!-- <BButton-->
<!-- variant="outline-light"-->
<!-- @click="toggleShowPassword"-->
<!-- class="border-left-0 rounded-right"-->
<!-- tabindex="-1"-->
<!-- >-->
<!-- &lt;!&ndash; <b-icon :icon="showPassword ? 'eye' : 'eye-slash'" />&ndash;&gt;-->
<!-- {{ showPassword ? 'eye' : 'eye-slash' }}-->
<!-- </BButton>-->
<!-- </template>-->
<!-- <BFormInvalidFeedback v-bind="ariaMsg">-->
<!-- <div v-if="props.showAllErrors">-->
<!-- <span v-for="error in errors" :key="error">-->
<!-- {{ error }}-->
<!-- <br />-->
<!-- </span>-->
<!-- </div>-->
<!-- <div v-else>-->
<!-- {{ errors[0] }}-->
<!-- </div>-->
<!-- </BFormInvalidFeedback>-->
<!-- </BInputGroup>-->
<!-- </BFormGroup>-->
<!-- </validation-provider>-->
<!--</template>-->
<template>
<div>
<BFormGroup :label="defaultTranslations.label" :label-for="labelFor">
@ -72,66 +25,26 @@
</BButton>
</template>
</BInputGroup>
<BFormInvalidFeedback v-bind="ariaMsg">
<!-- <div v-if="showAllErrors">-->
<!-- <span v-for="error in errors" :key="error">-->
<!-- {{ error }}-->
<!-- <br />-->
<!-- </span>-->
<!-- </div>-->
{{ errorMessage }}
<BFormInvalidFeedback v-if="errorMessage || errors.length" force-show v-bind="ariaMsg">
<template #default>
<div v-if="allowFullValidation">
<span v-for="error in errors" :key="error">
{{ error }}
<br />
</span>
</div>
<template v-else>{{ errorMessage }}</template>
</template>
</BFormInvalidFeedback>
</BFormGroup>
</div>
</template>
<!--<script>-->
<!--export default {-->
<!-- name: 'InputPassword',-->
<!-- props: {-->
<!-- rules: {-->
<!-- default: () => {-->
<!-- return {-->
<!-- required: true,-->
<!-- }-->
<!-- },-->
<!-- },-->
<!-- name: { type: String, default: 'password' },-->
<!-- label: { type: String, default: 'Password' },-->
<!-- placeholder: { type: String, default: 'Password' },-->
<!-- value: { required: true, type: String },-->
<!-- showAllErrors: { type: Boolean, default: false },-->
<!-- immediate: { type: Boolean, default: false },-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- currentValue: '',-->
<!-- showPassword: false,-->
<!-- }-->
<!-- },-->
<!-- computed: {-->
<!-- labelFor() {-->
<!-- return this.name + '-input-field'-->
<!-- },-->
<!-- },-->
<!-- methods: {-->
<!-- toggleShowPassword() {-->
<!-- this.showPassword = !this.showPassword-->
<!-- },-->
<!-- },-->
<!-- watch: {-->
<!-- currentValue() {-->
<!-- this.$emit('input', this.currentValue)-->
<!-- },-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, computed, watch, defineProps, defineEmits, toRef } from 'vue'
import { ref, computed, watch, defineProps, defineEmits, toRef, onMounted, nextTick } from 'vue'
import { useField } from 'vee-validate'
import { useI18n } from 'vue-i18n'
// Define props with default values
const props = defineProps({
name: {
type: String,
@ -145,25 +58,32 @@ const props = defineProps({
type: String,
default: 'Password',
},
modelValue: {
type: String,
required: true,
},
showAllErrors: {
immediate: {
type: Boolean,
default: false,
},
immediate: {
rules: {
type: Object || String,
default: 'required',
},
allowFullValidation: {
type: Boolean,
default: false,
},
})
const emit = defineEmits(['update:modelValue'])
const name = toRef(props, 'name')
// Use the useField hook for validation
const { value, errorMessage, meta } = useField(name, 'required')
const { value, errorMessage, meta, errors, validate } = useField(name, props.rules, {
bails: !props.allowFullValidation,
validateOnMount: props.immediate,
})
// onMounted(async () => {
// await nextTick()
// if (props.immediate) {
// await validate()
// }
// })
const { t } = useI18n()
@ -172,15 +92,12 @@ const defaultTranslations = computed(() => ({
placeholder: props.placeholder ?? t('form.password'),
}))
// Local state
const showPassword = ref(false)
// Toggle password visibility
const toggleShowPassword = () => {
showPassword.value = !showPassword.value
}
// Computed properties for ARIA attributes and labelFor
const ariaInput = computed(() => ({
'aria-invalid': meta.valid ? false : 'true',
'aria-describedby': `${props.name}-feedback`,

View File

@ -4,22 +4,20 @@
<BCol>
<input-password
id="new-password-input-field"
:model-value="password"
:rules="{
required: true,
containsLowercaseCharacter: true,
containsUppercaseCharacter: true,
containsNumericCharacter: true,
atLeastEightCharacters: true,
atLeastOneSpecialCharater: true,
atLeastOneSpecialCharacter: true,
noWhitespaceCharacters: true,
}"
:label="register ? $t('form.password') : $t('form.password_new')"
:show-all-errors="true"
:immediate="true"
:name="createId(register ? $t('form.password') : $t('form.password_new'))"
immediate
name="newPassword"
:placeholder="register ? $t('form.password') : $t('form.password_new')"
@update:modelValue="password = $event"
allow-full-validation
/>
</BCol>
</BRow>
@ -27,28 +25,21 @@
<BCol>
<input-password
id="repeat-new-password-input-field"
:model-value="passwordRepeat"
:rules="{
required: true,
samePassword: password,
samePassword: 'newPassword',
}"
:label="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
:immediate="true"
:name="createId(register ? $t('form.passwordRepeat') : $t('form.password_new_repeat'))"
immediate
name="newPasswordRepeat"
:placeholder="register ? $t('form.passwordRepeat') : $t('form.password_new_repeat')"
@update:modelValue="passwordRepeat = $event"
/>
</BCol>
</BRow>
</div>
</template>
<script setup>
import { computed, ref, watch } from 'vue'
import InputPassword from './InputPassword'
import { BCol, BRow } from 'bootstrap-vue-next'
const password = ref('')
const passwordRepeat = ref('')
defineProps({
modelValue: {
@ -60,22 +51,4 @@ defineProps({
required: false,
},
})
const emit = defineEmits(['input'])
const createId = (text) => {
return text.replace(/ +/g, '-')
}
const passwordObject = computed(() => {
return { password: password.value, passwordRepeat: passwordRepeat.value }
})
watch(
[password, passwordRepeat],
() => {
emit('input', passwordObject.value)
},
{ deep: true },
)
</script>

View File

@ -11,7 +11,6 @@
{{ lang.name }}
</span>
</span>
<!-- <b-icon icon="caret-down-fill" aria-hidden="true"></b-icon>-->
<IBiCaretDownFill />
</div>
<BCollapse id="collapse-1" class="mt-4">
@ -33,7 +32,7 @@
"
class="ml-3 mr-3"
>
{{ locales.length - 1 > index ? $t('math.pipe') : '' }}
{{ locales.length - 1 > index ? $t('|') : '' }}
</span>
</span>
</BCollapse>

View File

@ -1,10 +1,6 @@
<template>
<div class="language-switch-select">
<b-form-select
v-model="selected"
:options="options"
class="selectedLanguage mb-3"
></b-form-select>
<BFormSelect v-model="selected" :options="options" class="selectedLanguage mb-3"></BFormSelect>
</div>
</template>
<script>

View File

@ -1,6 +1,6 @@
<template>
<div class="redeem-logged-out">
<redeem-information v-bind="linkData" :is-contribution-link="isContributionLink" />
<redeem-information v-bind="props.linkData" :is-contribution-link="props.isContributionLink" />
<BCard>
<div class="mb-2">
@ -10,31 +10,25 @@
<BRow>
<BCol sm="12" md="6">
<p>{{ $t('gdd_per_link.no-account') }}</p>
<BButton variant="primary" :to="register">
<BButton variant="primary" :to="register()">
{{ $t('gdd_per_link.to-register') }}
</BButton>
</BCol>
<BCol sm="12" md="6" class="mt-4 mt-lg-0">
<p>{{ $t('gdd_per_link.has-account') }}</p>
<BButton variant="gradido" :to="login">{{ $t('gdd_per_link.to-login') }}</BButton>
<BButton variant="gradido" :to="login()">{{ $t('gdd_per_link.to-login') }}</BButton>
</BCol>
</BRow>
</BCard>
</div>
</template>
<script>
import RedeemInformation from '@/components/LinkInformations/RedeemInformation'
import { authLinks } from '@/mixins/authLinks'
export default {
name: 'RedeemLoggedOut',
components: {
RedeemInformation,
},
mixins: [authLinks],
props: {
linkData: { type: Object, required: true },
isContributionLink: { type: Boolean, default: false },
},
}
<script setup>
import { useAuthLinks } from '@/composables/useAuthLinks'
const { login, register } = useAuthLinks()
const props = defineProps({
linkData: { type: Object, required: true },
isContributionLink: { type: Boolean, default: false },
})
</script>

View File

@ -41,12 +41,14 @@
<BNav vertical class="w-100">
<BNavItem
to="/settings"
class="mb-3"
class="mb-3 d-block"
active-class="active-route"
data-test="settings-menu"
>
<BImg src="/img/svg/settings.svg" height="20" class="svg-icon" />
<span class="ml-2">{{ $t('navigation.settings') }}</span>
<div>
<BImg src="/img/svg/settings.svg" height="20" class="svg-icon" />
<span class="ml-2">{{ $t('navigation.settings') }}</span>
</div>
<BBadge v-if="!$store.state.username" variant="warning">
{{ $t('settings.newSettings') }}
</BBadge>
@ -106,6 +108,7 @@ export default {
}
.active-route {
display: block;
font-weight: bold;
color: rgb(2 2 1);
border-left: 4px rgb(219 129 19) solid;

View File

@ -29,7 +29,7 @@
</BRow>
</BCard>
<template #modal-footer>
<BButton size="sm" variant="danger" @click="$emit('logout')">
<BButton size="sm" variant="danger" @click="emit('logout')">
{{ $t('navigation.logout') }}
</BButton>
<BButton size="lg" variant="success" @click="handleOk">
@ -39,83 +39,21 @@
</BModal>
</div>
</template>
<!--<script>-->
<!--import { verifyLogin } from '@/graphql/queries'-->
<!--export default {-->
<!-- name: 'SessionLogoutTimeout',-->
<!-- data() {-->
<!-- return {-->
<!-- now: new Date().getTime(),-->
<!-- }-->
<!-- },-->
<!-- timers: {-->
<!-- tokenExpires: {-->
<!-- time: 15000,-->
<!-- autostart: true,-->
<!-- repeat: true,-->
<!-- immediate: true,-->
<!-- },-->
<!-- },-->
<!-- methods: {-->
<!-- tokenExpires() {-->
<!-- this.now = new Date().getTime()-->
<!-- if (this.tokenExpiresInSeconds < 75 && this.timers.tokenExpires.time !== 1000) {-->
<!-- this.timers.tokenExpires.time = 1000-->
<!-- this.$timer.restart('tokenExpires')-->
<!-- this.$bvModal.show('modalSessionTimeOut')-->
<!-- }-->
<!-- if (this.tokenExpiresInSeconds === 0) {-->
<!-- this.$timer.stop('tokenExpires')-->
<!-- this.$emit('logout')-->
<!-- }-->
<!-- },-->
<!-- handleOk(bvModalEvent) {-->
<!-- bvModalEvent.preventDefault()-->
<!-- this.$apollo-->
<!-- .query({-->
<!-- query: verifyLogin,-->
<!-- fetchPolicy: 'network-only',-->
<!-- })-->
<!-- .then((result) => {-->
<!-- this.timers.tokenExpires.time = 15000-->
<!-- this.$timer.restart('tokenExpires')-->
<!-- this.$bvModal.hide('modalSessionTimeOut')-->
<!-- })-->
<!-- .catch(() => {-->
<!-- this.$timer.stop('tokenExpires')-->
<!-- this.$emit('logout')-->
<!-- })-->
<!-- },-->
<!-- },-->
<!-- computed: {-->
<!-- tokenExpiresInSeconds() {-->
<!-- const remainingSecs = Math.floor(-->
<!-- (new Date(this.$store.state.tokenTime * 1000).getTime() - this.now) / 1000,-->
<!-- )-->
<!-- return remainingSecs <= 0 ? 0 : remainingSecs-->
<!-- },-->
<!-- },-->
<!-- beforeDestroy() {-->
<!-- this.$timer.stop('tokenExpires')-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
// TODO to be checked and fixed
import { ref, computed, onBeforeUnmount } from 'vue'
import { ref, computed, onBeforeUnmount, watch } from 'vue'
import { useStore } from 'vuex'
import { useLazyQuery } from '@vue/apollo-composable'
import { useTimer } from 'vue-timer-hook' // TODO change to updated version
import { useModal } from 'bootstrap-vue-next'
import { verifyLogin } from '@/graphql/queries'
import { useModal } from 'bootstrap-vue-next'
const store = useStore()
const { result, load: verifyLoginQuery } = useLazyQuery(verifyLogin)
const { modal } = useModal()
const timer = useTimer()
const emit = defineEmits(['logout'])
const { show: showModal, hide: hideModal } = useModal('modalSessionTimeOut')
const { load: verifyLoginQuery, loading, error } = useLazyQuery(verifyLogin)
const timerInterval = ref(null)
const now = ref(new Date().getTime())
@ -126,47 +64,66 @@ const tokenExpiresInSeconds = computed(() => {
return remainingSecs <= 0 ? 0 : remainingSecs
})
const handleOk = async () => {
return 'OK'
const updateNow = () => {
now.value = new Date().getTime()
}
// const tokenExpires = () => {
// now.value = new Date().getTime()
// if (tokenExpiresInSeconds.value < 75 && timer.value.tokenExpires.time !== 1000) {
// timer.value.tokenExpires.time = 1000
// restartTimer('tokenExpires')
// modal.show('modalSessionTimeOut')
// }
// if (tokenExpiresInSeconds.value === 0) {
// stopTimer('tokenExpires')
// emit('logout')
// }
// }
//
// const handleOk = (bvModalEvent) => {
// bvModalEvent.preventDefault()
// verifyLoginQuery({
// fetchPolicy: 'network-only',
// })
// .then(() => {
// timer.value.tokenExpires.time = 15000
// restartTimer('tokenExpires')
// modal.hide('modalSessionTimeOut')
// })
// .catch(() => {
// stopTimer('tokenExpires')
// emit('logout')
// })
// }
//
// // Start the timer
// startTimer('tokenExpires', {
// time: 15000,
// callback: tokenExpires,
// immediate: true,
// })
//
// onBeforeUnmount(() => {
// stopTimer('tokenExpires')
// })
const checkExpiration = () => {
if (tokenExpiresInSeconds.value < 75 && !timerInterval.value) {
showModal()
}
if (tokenExpiresInSeconds.value === 0) {
stopTimer()
emit('logout')
}
}
const handleOk = async (bvModalEvent) => {
bvModalEvent.preventDefault()
try {
await verifyLoginQuery()
if (error.value) {
throw new Error('Login verification failed')
}
hideModal('modalSessionTimeOut')
} catch {
stopTimer()
emit('logout')
}
}
const startTimer = () => {
stopTimer()
timerInterval.value = setInterval(() => {
updateNow()
checkExpiration()
}, 1000)
}
const stopTimer = () => {
if (timerInterval.value) {
clearInterval(timerInterval.value)
timerInterval.value = null
}
}
watch(
tokenExpiresInSeconds,
(newValue) => {
if (newValue < 75 && !timerInterval.value) {
startTimer()
} else if (newValue >= 75 && timerInterval.value) {
stopTimer()
}
},
{ immediate: true },
)
onBeforeUnmount(() => {
stopTimer()
})
checkExpiration()
const emit = defineEmits(['logout'])
</script>

View File

@ -28,7 +28,7 @@
<!-- icon="layers"-->
<!-- class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"-->
<!-- ></b-icon>-->
<IBiLayers />
<IBiLayers class="mr-3 gradido-global-border-color-accent" />
<span v-if="hideAmount" class="font-weight-bold gradido-global-color-accent">
{{ $t('asterisks') }}
</span>
@ -37,14 +37,9 @@
</span>
</BCol>
<BCol cols="3" class="border-left border-light">
<!-- <b-icon-->
<!-- :icon="hideAmount ? 'eye-slash' : 'eye'"-->
<!-- class="mr-3 gradido-global-border-color-accent pointer hover-icon"-->
<!-- @click="updateHideAmountGDD"-->
<!-- ></b-icon>-->
<button class="transparent-button" @click="updateHideAmountGDD">
<IBiEyeSlash v-if="hideAmount" />
<IBiEye v-else />
<IBiEyeSlash v-if="hideAmount" class="mr-3 gradido-global-border-color-accent" />
<IBiEye v-else class="mr-3 gradido-global-border-color-accent" />
</button>
</BCol>
</BRow>
@ -58,7 +53,7 @@ import { useStore } from 'vuex'
import { useMutation } from '@vue/apollo-composable'
import { useI18n } from 'vue-i18n'
import { updateUserInfos } from '@/graphql/mutations'
import { useAppToast } from '../../../composables/useToast'
import { useAppToast } from '@/composables/useToast'
const props = defineProps({
path: { type: String, required: false, default: '' },

View File

@ -11,9 +11,6 @@
/>
</BCol>
<BCol>
<!-- <div>
{{ getLinesByType }}
</div> -->
<div>
<span class="small">{{ $d(new Date(date), 'short') }}</span>
<span class="small ml-3">{{ $d(new Date(date), 'time') }}</span>
@ -45,102 +42,14 @@
</div>
</div>
</template>
<!--<script>-->
<!--import CollapseIcon from './TransactionRows/CollapseIcon'-->
<!--import TransactionCollapse from './TransactionCollapse'-->
<!--import { GdtEntryType } from '../graphql/enums'-->
<!--export default {-->
<!-- name: 'Transaction',-->
<!-- components: {-->
<!-- CollapseIcon,-->
<!-- TransactionCollapse,-->
<!-- },-->
<!-- props: {-->
<!-- amount: { type: Number },-->
<!-- date: { type: String },-->
<!-- comment: { type: String },-->
<!-- gdtEntryType: { type: String, default: GdtEntryType.FORM },-->
<!-- factor: { type: Number },-->
<!-- gdt: { type: Number },-->
<!-- id: { type: Number },-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- collapseStatus: [],-->
<!-- visible: false,-->
<!-- }-->
<!-- },-->
<!-- methods: {-->
<!-- getCollapseState(id) {-->
<!-- return this.collapseStatus.includes('gdt-collapse-' + id)-->
<!-- },-->
<!-- },-->
<!-- computed: {-->
<!-- collapseId() {-->
<!-- return 'gdt-collapse-' + String(this.id)-->
<!-- },-->
<!-- isGlobalModificator() {-->
<!-- return this.gdtEntryType === GdtEntryType.GLOBAL_MODIFICATOR-->
<!-- },-->
<!-- getLinesByType() {-->
<!-- switch (this.gdtEntryType) {-->
<!-- case GdtEntryType.FORM:-->
<!-- case GdtEntryType.CVS:-->
<!-- case GdtEntryType.ELOPAGE:-->
<!-- case GdtEntryType.DIGISTORE:-->
<!-- case GdtEntryType.CVS2: {-->
<!-- return {-->
<!-- icon: 'heart',-->
<!-- iconclasses: 'gradido-global-color-accent',-->
<!-- description: this.$t('gdt.contribution'),-->
<!-- descriptiontext: this.$n(this.amount, 'decimal') + ' €',-->
<!-- credittext: this.$n(this.gdt, 'decimal') + ' GDT',-->
<!-- }-->
<!-- }-->
<!-- case GdtEntryType.ELOPAGE_PUBLISHER: {-->
<!-- return {-->
<!-- icon: 'person-check',-->
<!-- iconclasses: 'gradido-global-color-accent',-->
<!-- description: this.$t('gdt.recruited-member'),-->
<!-- descriptiontext: '5%',-->
<!-- credittext: this.$n(this.amount, 'decimal') + ' GDT',-->
<!-- }-->
<!-- }-->
<!-- case GdtEntryType.GLOBAL_MODIFICATOR: {-->
<!-- return {-->
<!-- icon: 'gift',-->
<!-- iconclasses: 'gradido-global-color-accent',-->
<!-- description: this.$t('gdt.gdt-received'),-->
<!-- descriptiontext: this.comment,-->
<!-- credittext: this.$n(this.gdt, 'decimal') + ' GDT',-->
<!-- }-->
<!-- }-->
<!-- default:-->
<!-- throw new Error('no lines for this type: ' + this.gdtEntryType)-->
<!-- }-->
<!-- },-->
<!-- },-->
<!-- mounted() {-->
<!-- this.$root.$on('bv::collapse::state', (collapseId, isJustShown) => {-->
<!-- if (isJustShown) {-->
<!-- this.collapseStatus.push(collapseId)-->
<!-- } else {-->
<!-- this.collapseStatus = this.collapseStatus.filter((id) => id !== collapseId)-->
<!-- }-->
<!-- })-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, computed, onMounted } from 'vue'
import { ref, computed, onMounted, getCurrentInstance } from 'vue'
import { useI18n } from 'vue-i18n'
import CollapseIcon from './TransactionRows/CollapseIcon'
import TransactionCollapse from './TransactionCollapse'
import { GdtEntryType } from '../graphql/enums'
// Props
const props = defineProps({
amount: Number,
date: String,
@ -154,20 +63,13 @@ const props = defineProps({
id: Number,
})
// Reactive state
const collapseStatus = ref([])
const visible = ref(false)
const { t, n } = useI18n()
const getCollapseState = (id) => {
return collapseStatus.value.includes('gdt-collapse-' + id)
}
const collapseId = computed(() => 'gdt-collapse-' + String(props.id))
const isGlobalModificator = computed(() => props.gdtEntryType === GdtEntryType.GLOBAL_MODIFICATOR)
const getLinesByType = computed(() => {
switch (props.gdtEntryType) {
case GdtEntryType.FORM:
@ -208,14 +110,13 @@ const getLinesByType = computed(() => {
onMounted(() => {
// Note: This event listener setup might need to be adjusted for Vue 3
// You might want to use provide/inject or a global event bus instead
// const root = getCurrentInstance().appContext.config.globalProperties
// root.$on('bv::collapse::state', (collapseId, isJustShown) => {
// if (isJustShown) {
// collapseStatus.value.push(collapseId)
// } else {
// collapseStatus.value = collapseStatus.value.filter((id) => id !== collapseId)
// }
// })
const root = getCurrentInstance().appContext.config.globalProperties
root.$on('bv::collapse::state', (collapseId, isJustShown) => {
if (isJustShown) {
collapseStatus.value.push(collapseId)
} else {
collapseStatus.value = collapseStatus.value.filter((id) => id !== collapseId)
}
})
})
</script>

View File

@ -15,26 +15,30 @@
<BCol cols="12" lg="1" md="1" class="text-center text-md-right pr-5 pr-lg-4">
<BDropdown no-caret right aria-expanded="false" size="sm">
<template #button-content>
<IBiThreeDotsVertical />
<IBiThreeDotsVertical class="link-menu-opener" />
</template>
<BDropdownItem v-if="validLink" class="test-copy-link" @click="copyToClipboard">
<BDropdownItem v-if="validLink" class="test-copy-link" @click.stop="copyLink">
<IBiClipboard />
{{ $t('gdd_per_link.copy-link') }}
</BDropdownItem>
<BDropdownItem v-if="validLink" class="test-copy-text pt-3" @click="copyLinkWithText">
<BDropdownItem
v-if="validLink"
class="test-copy-text pt-3"
@click.stop="copyLinkWithText"
>
<IBiClipboardPlus />
{{ $t('gdd_per_link.copy-link-with-text') }}
</BDropdownItem>
<BDropdownItem
v-if="validLink"
class="pt-3 pb-3 test-qr-code"
@click="$bvModal.show('modalPopover-' + id)"
@click.stop="toggleQrModal"
>
<BImg src="img/svg/qr-code.svg" width="18" class="filter"></BImg>
{{ $t('qrCode') }}
</BDropdownItem>
<BDropdownItem class="test-delete-link" @click="deleteLink()">
<BDropdownItem class="test-delete-link" @click.stop="toggleDeleteModal">
<IBiTrash />
{{ $t('delete') }}
</BDropdownItem>
@ -43,7 +47,7 @@
</BRow>
</BCol>
</BRow>
<BModal :id="'modalPopover-' + id" ok-only hide-header-close>
<app-modal :model-value="showQrModal" @update:model-value="toggleQrModal">
<BCard header-tag="header" footer-tag="footer">
<template #header>
<h6 class="mb-0">{{ $t('qrCode') }}</h6>
@ -53,20 +57,25 @@
<em>{{ link }}</em>
</template>
</BCard>
</BModal>
<BModal :id="'modalPopoverCopyError' + id" ok-only hide-header-close>
</app-modal>
<app-modal
id="delete-link-modal"
:model-value="showDeleteLinkModal"
ok-only
@update:model-value="toggleDeleteModal"
@on-ok="deleteLink"
>
<BCard header-tag="header" footer-tag="footer">
<BCardText>
<div class="alert-danger p-3">{{ $t('gdd_per_link.not-copied') }}</div>
<div class="alert-muted h3 p-3">{{ link }}</div>
</BCardText>
<h6 class="mb-0">{{ $t('gdd_per_link.delete-the-link') }}</h6>
<br />
<em>{{ link }}</em>
</BCard>
</BModal>
</app-modal>
</div>
</template>
<script setup>
import { computed } from 'vue'
import { computed, ref } from 'vue'
import { useMutation } from '@vue/apollo-composable'
import { useI18n } from 'vue-i18n'
import { useAppToast } from '@/composables/useToast'
@ -77,8 +86,8 @@ import AmountAndNameRow from '../TransactionRows/AmountAndNameRow'
import MemoRow from '../TransactionRows/MemoRow'
import DateRow from '../TransactionRows/DateRow'
import DecayRow from '../TransactionRows/DecayRow'
import AppModal from '@/components/AppModal'
import FigureQrCode from '@/components/QrCode/FigureQrCode'
import { useModal } from 'bootstrap-vue-next'
const props = defineProps({
holdAvailableAmount: { type: String, required: true },
@ -89,17 +98,19 @@ const props = defineProps({
memo: { type: String, required: true },
})
const showQrModal = ref(false)
const showDeleteLinkModal = ref(false)
const emit = defineEmits(['reset-transaction-link-list'])
const { t } = useI18n()
const { toastSuccess, toastError } = useAppToast()
const { copyToClipboard, copyLinkWithText } = useCopyLinks({
const { copyLink, copyLinkWithText } = useCopyLinks({
amount: props.amount,
validUntil: props.validUntil,
link: props.link,
memo: props.memo,
})
const { showConfirmModal } = useModal()
const { mutate: deleteTransactionLinkMutation } = useMutation(deleteTransactionLink)
@ -107,25 +118,22 @@ const decay = computed(() => `${props.amount - props.holdAvailableAmount}`)
const validLink = computed(() => new Date(props.validUntil) > new Date())
async function deleteLink() {
const confirmed = await showConfirmModal(t('gdd_per_link.delete-the-link'))
if (confirmed) {
try {
await deleteTransactionLinkMutation({ id: props.id })
toastSuccess(t('gdd_per_link.deleted'))
emit('reset-transaction-link-list')
} catch (err) {
toastError(err.message)
}
try {
await deleteTransactionLinkMutation({ id: props.id })
toastSuccess(t('gdd_per_link.deleted'))
emit('reset-transaction-link-list')
} catch (err) {
toastError(err.message)
}
}
// Expose necessary methods and computed properties
// defineExpose({
// deleteLink,
// decay,
// validLink,
// copyToClipboard,
// })
const toggleDeleteModal = () => {
showDeleteLinkModal.value = !showDeleteLinkModal.value
}
const toggleQrModal = () => {
showQrModal.value = !showQrModal.value
}
</script>
<style>
.qr-button {

View File

@ -1,5 +1,5 @@
<template>
<div class="transaction-slot-link" @click="showTransactionLinks()">
<div class="transaction-slot-link" @click="showTransactionLinks">
<BRow class="align-items-center">
<BCol cols="3" lg="2" md="2">
<BAvatar icon="link" variant="light" :size="42"></BAvatar>
@ -69,7 +69,11 @@ watch(currentPage, () => {
updateListTransactionLinks()
})
function showTransactionLinks() {
function showTransactionLinks(evt) {
const targetClassNames = [...evt.target.classList]
if (targetClassNames.includes('link-menu-opener') || targetClassNames.includes('btn-secondary')) {
return
}
if (visible.value) {
visible.value = false
} else {

View File

@ -3,11 +3,17 @@
<div>
<BRow class="mb-4 text-right">
<BCol class="text-right">
<button data-test="open-password-change-form" @click="toggleShowPassword">
<BButton
class="change-password-form-opener"
data-test="open-password-change-form"
@click="toggleShowPassword"
>
<span class="pointer mr-3">{{ $t('settings.password.change-password') }}</span>
<IBiPencil v-if="showPassword" />
<IBiXCircle v-else class="color-danger" />
<!-- <b-icon v-if="showPassword" class="pointer ml-3" icon="pencil"></b-icon>
<b-icon v-else icon="x-circle" class="pointer ml-3" variant="danger"></b-icon> -->
</button>
</BButton>
</BCol>
</BRow>
</div>
@ -66,26 +72,27 @@ const showPassword = ref(true)
const register = ref(false)
const form = ref({
password: '',
newPassword: {
password: '',
passwordRepeat: '',
},
newPassword: '',
newPasswordRepeat: '',
})
const { toastError, toastSuccess } = useAppToast()
const { handleSubmit, invalid } = useForm({
initialValues: form.value,
const {
handleSubmit,
invalid,
values: formValues,
resetForm,
} = useForm({
initialValues: { ...form.value },
})
const disabled = computed(() => {
return form.value.newPassword.password !== form.value.newPassword.passwordRepeat
return formValues.newPassword !== formValues.newPasswordRepeat
})
const cancelEdit = () => {
showPassword.value = true
form.value.password = ''
form.value.passwordNew = ''
form.value.passwordNewRepeat = ''
resetForm()
}
const toggleShowPassword = () => {
@ -97,8 +104,8 @@ const { mutate: updateUserInfo } = useMutation(updateUserInfos)
const onSubmit = handleSubmit(async () => {
try {
await updateUserInfo({
password: form.value.password,
passwordNew: form.value.newPassword.password,
password: formValues.password,
passwordNew: formValues.newPassword,
})
toastSuccess(t('message.reset'))
cancelEdit()
@ -107,3 +114,27 @@ const onSubmit = handleSubmit(async () => {
}
})
</script>
<style scoped lang="scss">
.change-password-form-opener {
background-color: transparent;
border: none;
color: $gradido-4;
display: flex;
align-items: center;
margin-left: auto;
> span {
margin-right: 15px;
}
> svg {
width: 16px;
height: 16px;
}
}
.color-danger {
color: $danger !important;
}
</style>

View File

@ -24,7 +24,7 @@ export const useCopyLinks = ({ link, amount, memo, validUntil }) => {
const copyLinkWithText = () => {
navigator.clipboard
.writeText(linkText)
.writeText(linkText.value)
.then(() => {
toastSuccess(t('gdd_per_link.link-and-text-copied'))
})
@ -39,7 +39,7 @@ export const useCopyLinks = ({ link, amount, memo, validUntil }) => {
${store.state.firstName} ${t('transaction-link.send_you')} ${amount} Gradido.
"${memo}"
${t('gdd_per_link.credit-your-gradido')} ${t('gdd_per_link.validUntilDate', {
date: d(new Date(this.validUntil), 'short'),
date: d(new Date(validUntil), 'short'),
})}
${t('gdd_per_link.link-hint')}`
})

View File

@ -51,12 +51,13 @@
triggers="click"
placement="top"
variant="dark"
custom-class="login-size-controller"
>
<div class="text-light">
<span class="pointer" @click="setTextSize(0.85)">{{ $t('85') }}</span>
{{ $t('math.pipe') }}
{{ $t('|') }}
<span class="pointer" @click="setTextSize(1)">{{ $t('100') }}</span>
{{ $t('math.pipe') }}
{{ $t('|') }}
<span class="pointer" @click="setTextSize(1.25)">{{ $t('125') }}</span>
</div>
</BPopover>
@ -165,4 +166,8 @@ export default {
font-size: xx-large;
}
}
.login-size-controller {
background-color: #212529;
}
</style>

View File

@ -178,13 +178,12 @@
<BRow>
<!-- footer -->
<BCol>
<content-footer v-if="!$route.meta.hideFooter"></content-footer>
<content-footer v-if="!$route.meta.hideFooter" />
</BCol>
</BRow>
<session-logout-timeout @logout="logoutUser"></session-logout-timeout>
<!-- <session-logout-timeout @logout="logoutUser" ref="sessionModal" />-->
</div>
</div>
<!-- <h1>TEST</h1>-->
</template>
<script setup>
@ -234,6 +233,12 @@ const darkMode = ref(false)
const skeleton = ref(true)
const totalUsers = ref(null)
const sessionModal = ref(null)
const testModal = () => {
sessionModal.value.showTimeoutModalForTesting()
}
onMounted(() => {
updateTransactions({ currentPage: 0, pageSize: 10 })
getCommunityStatistics()

View File

@ -121,7 +121,6 @@
"error": {
"email-already-sent": "Wir haben dir bereits eine E-Mail vor weniger als 10 Minuten geschickt.",
"empty-transactionlist": "Es gab einen Fehler mit der Übermittlung der Anzahl deiner Transaktionen.",
"error": "Fehler!",
"no-account": "Leider konnten wir keinen (aktivierten) Account mit diesen Daten finden.",
"no-transactionlist": "Es gab leider einen Fehler. Es wurden keine Transaktionen vom Server übermittelt.",
"no-user": "Kein Benutzer mit diesen Anmeldedaten.",
@ -161,6 +160,7 @@
"message": "Nachricht",
"new_balance": "Neuer Kontostand nach Bestätigung",
"no_gdd_available": "Du hast keine GDD zum versenden.",
"ok": "Ok",
"password": "Passwort",
"passwordRepeat": "Passwort wiederholen",
"password_new": "Neues Passwort",
@ -252,8 +252,7 @@
"math": {
"asterisk": "*",
"equal": "=",
"minus": "",
"pipe": "|"
"minus": ""
},
"maxReached": "Max. erreicht",
"member": "Mitglied",

View File

@ -121,7 +121,6 @@
"error": {
"email-already-sent": "We already sent you an email less than 10 minutes ago.",
"empty-transactionlist": "There was an error with the transmission of the number of your transactions.",
"error": "Error!",
"no-account": "Unfortunately we could not find an (activated) account to the given data.",
"no-transactionlist": "Unfortunately, there was an error. No transactions have been sent from the server.",
"no-user": "No user with this credentials.",
@ -161,6 +160,7 @@
"message": "Message",
"new_balance": "Account balance after confirmation",
"no_gdd_available": "You do not have GDD to send.",
"ok": "Ok",
"password": "Password",
"passwordRepeat": "Repeat password",
"password_new": "New password",
@ -252,8 +252,7 @@
"math": {
"asterisk": "*",
"equal": "=",
"minus": "",
"pipe": "|"
"minus": ""
},
"maxReached": "Max. reached",
"member": "Member",

View File

@ -1,12 +0,0 @@
export const authLinks = {
computed: {
login() {
if (this.$route.params.code) return '/login/' + this.$route.params.code
return '/login'
},
register() {
if (this.$route.params.code) return '/register/' + this.$route.params.code
return '/register'
},
},
}

View File

@ -1,48 +0,0 @@
export const copyLinks = {
props: {
link: { type: String, required: true },
amount: { type: String, required: true },
memo: { type: String, required: true },
validUntil: { type: String, required: true },
},
data() {
return {
canCopyLink: true,
}
},
methods: {
copyLink() {
navigator.clipboard
.writeText(this.link)
.then(() => {
this.toastSuccess(this.$t('gdd_per_link.link-copied'))
})
.catch(() => {
this.canCopyLink = false
this.toastError(this.$t('gdd_per_link.not-copied'))
})
},
copyLinkWithText() {
navigator.clipboard
.writeText(this.linkText)
.then(() => {
this.toastSuccess(this.$t('gdd_per_link.link-and-text-copied'))
})
.catch(() => {
this.canCopyLink = false
this.toastError(this.$t('gdd_per_link.not-copied'))
})
},
},
computed: {
linkText() {
return `${this.link}
${this.$store.state.firstName} ${this.$t('transaction-link.send_you')} ${this.amount} Gradido.
"${this.memo}"
${this.$t('gdd_per_link.credit-your-gradido')} ${this.$t('gdd_per_link.validUntilDate', {
date: this.$d(new Date(this.validUntil), 'short'),
})}
${this.$t('gdd_per_link.link-hint')}`
},
},
}

View File

@ -1,42 +0,0 @@
export const toasters = {
methods: {
toastSuccess(message) {
this.toast(message, {
title: this.$t('success'),
variant: 'success',
})
},
toastError(message) {
this.toast(message, {
title: this.$t('error.error'),
variant: 'danger',
})
},
toastInfo(message) {
this.toast(message, {
title: this.$t('navigation.info'),
variant: 'warning',
})
},
toastInfoNoHide(message) {
this.toast(message, {
title: this.$t('navigation.info'),
variant: 'warning',
noAutoHide: true,
})
},
toast(message, options) {
if (message.replace) message = message.replace(/^GraphQL error: /, '')
this.$root.$bvToast.toast(message, {
appendToast: true,
autoHideDelay: 5000,
solid: true,
toaster: 'b-toaster-top-right',
headerClass: 'gdd-toaster-title',
bodyClass: 'gdd-toaster-body',
toastClass: 'gdd-toaster',
...options,
})
},
},
}

View File

@ -1,59 +1,3 @@
<!--<template>-->
<!-- <div class="login-form">-->
<!-- <BContainer v-if="enterData">-->
<!-- <div class="pb-5" align="center">{{ $t('gdd_per_link.isFree') }}</div>-->
<!-- <validation-observer ref="observer" v-slot="{ handleSubmit, valid }">-->
<!-- <BForm @submit.stop.prevent="handleSubmit(onSubmit)">-->
<!-- <BRow>-->
<!-- <BCol sm="12" md="12" lg="6">-->
<!-- <input-email-->
<!-- v-model="form.email"-->
<!-- :name="$t('form.email')"-->
<!-- :label="$t('form.email')"-->
<!-- :placeholder="$t('form.email')"-->
<!-- />-->
<!-- </BCol>-->
<!-- <BCol sm="12" md="12" lg="6">-->
<!-- <input-password-->
<!-- :label="$t('form.password')"-->
<!-- :placeholder="$t('form.password')"-->
<!-- :name="$t('form.password')"-->
<!-- v-model="form.password"-->
<!-- ></input-password>-->
<!-- </BCol>-->
<!-- </BRow>-->
<!-- <BRow>-->
<!-- <BCol class="d-flex justify-content-end mb-4 mb-lg-0">-->
<!-- <router-link to="/forgot-password" data-test="forgot-password-link">-->
<!-- {{ $t('settings.password.forgot_pwd') }}-->
<!-- </router-link>-->
<!-- </BCol>-->
<!-- </BRow>-->
<!-- <BRow>-->
<!-- <BCol cols="12" lg="6">-->
<!-- <BButton-->
<!-- type="submit"-->
<!-- :variant="valid ? 'gradido' : 'gradido-disable'"-->
<!-- block-->
<!-- :disabled="!valid"-->
<!-- >-->
<!-- {{ $t('login') }}-->
<!-- </BButton>-->
<!-- </BCol>-->
<!-- </BRow>-->
<!-- </BForm>-->
<!-- </validation-observer>-->
<!-- </BContainer>-->
<!-- <BContainer v-else>-->
<!-- <message-->
<!-- :headline="$t('message.errorTitle')"-->
<!-- :subtitle="errorSubtitle"-->
<!-- :buttonText="$t('settings.password.reset')"-->
<!-- :linkTo="errorLinkTo"-->
<!-- />-->
<!-- </BContainer>-->
<!-- </div>-->
<!--</template>-->
<template>
<div class="login-form">
<BContainer v-if="enterData">

View File

@ -61,7 +61,7 @@ const linkData = ref({
const redeemedBoxText = ref('')
const { result, loading, error } = useQuery(queryTransactionLink, {
const { result, onResult, loading, error, onError } = useQuery(queryTransactionLink, {
code: params.code,
})
@ -133,21 +133,26 @@ function updateRedeemedBoxText(type) {
const emit = defineEmits(['set-mobile-start'])
onMounted(() => {
setTransactionLinkInformation()
emit('set-mobile-start', false)
})
onResult(() => {
if (!result || !result.value) return
setTransactionLinkInformation()
})
onError(() => {
toastError(t('gdd_per_link.redeemlink-error'))
})
function setTransactionLinkInformation() {
result.value
.then((data) => {
linkData.value = data.queryTransactionLink
if (linkData.value.__typename === 'ContributionLink' && store.state.token) {
mutationLink(linkData.value.amount)
}
})
.catch(() => {
toastError(t('gdd_per_link.redeemlink-error'))
})
const { queryTransactionLink } = result.value
if (queryTransactionLink) {
linkData.value = queryTransactionLink
if (linkData.value.__typename === 'ContributionLink' && store.state.token) {
mutationLink(linkData.value.amount)
}
}
}
async function mutationLink(amount) {

View File

@ -1,183 +1,3 @@
// import { configure, defineRule } from 'vee-validate'
// // eslint-disable-next-line camelcase
// import { email, min, max, is_not, required } from '@vee-validate/rules'
// import { checkUsername } from '@/graphql/queries'
// import { validate as validateUuid, version as versionUuid } from 'uuid'
// import * as yup from 'yup'
//
// // taken from vee-validate
// // eslint-disable-next-line no-useless-escape
// const EMAIL_REGEX = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
//
// const USERNAME_REGEX = /^(?=.{3,20}$)[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+?)*$/
//
// export const loadAllRules = (i18nCallback, apollo) => {
// console.log('loadAllRules')
// console.log(i18nCallback)
// configure({
// defaultMessage: (field, values) => {
// // eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
// values._field_ = i18nCallback.t(`fields.${field}`)
// // eslint-disable-next-line @intlify/vue-i18n/no-dynamic-keys
// return i18nCallback.t(`validations.messages.${values._rule_}`, values)
// },
// classes: {
// valid: 'is-valid',
// invalid: 'is-invalid',
// dirty: ['is-dirty', 'is-dirty'], // multiple classes per flag!
// },
// })
//
// defineRule('email', (value) => {
// const isValid = email(value)
// if (!isValid) {
// return i18nCallback.t('validations.messages.email', value)
// }
// return true
// })
//
// defineRule('required', (value) => {
// const valueExists = required(value)
// if (!valueExists) {
// return i18nCallback.t('validations.messages.required', value)
// }
// return true
// })
//
// defineRule('min', (value, limit) => {
// return min(value, limit) ? true : i18nCallback.t('validations.messages.min', value)
// })
//
// defineRule('max', (value, limit) => {
// return max(value, limit) ? true : i18nCallback.t('validations.messages.max', value)
// })
// //
// // defineRule('gddSendAmount', {
// // validate(value, { min, max }) {
// // value = value.replace(',', '.')
// // return value.match(/^[0-9]+(\.[0-9]{0,2})?$/) && Number(value) >= min && Number(value) <= max
// // },
// // params: ['min', 'max'],
// // message: (_, values) => {
// // values.min = i18nCallback.n(values.min, 'ungroupedDecimal')
// // values.max = i18nCallback.n(values.max, 'ungroupedDecimal')
// // return i18nCallback.t('form.validation.gddSendAmount', values)
// // },
// // })
// //
// // defineRule('gddCreationTime', {
// // validate(value, { min, max }) {
// // return value >= min && value <= max
// // },
// // params: ['min', 'max'],
// // message: (_, values) => {
// // // values.min = values.min
// // // values.max = values.max
// // return i18nCallback.t('form.validation.gddCreationTime', values)
// // },
// // })
// //
// // // eslint-disable-next-line camelcase
// // defineRule('is_not', {
// // // eslint-disable-next-line camelcase
// // ...is_not,
// // message: (_, values) => i18nCallback.t('form.validation.is-not', values),
// // })
// //
// // // Password validation
// //
// defineRule('containsLowercaseCharacter', (value) => {
// const valid = !!value.match(/[a-z]+/)
// if (!valid) {
// return i18nCallback.t('site.signup.lowercase', { value })
// }
// return true
// })
//
// defineRule('containsUppercaseCharacter', (value) => {
// const isValid = !!value.match(/[A-Z]+/)
// if (!isValid) {
// i18nCallback.t('site.signup.uppercase', { value })
// }
// })
//
// // defineRule('containsNumericCharacter', {
// // validate(value) {
// // return !!value.match(/[0-9]+/)
// // },
// // message: (_, values) => i18nCallback.t('site.signup.one_number', values),
// // })
// //
// // defineRule('atLeastEightCharacters', {
// // validate(value) {
// // return !!value.match(/.{8,}/)
// // },
// // message: (_, values) => i18nCallback.t('site.signup.minimum', values),
// // })
// //
// // defineRule('atLeastOneSpecialCharater', {
// // validate(value) {
// // return !!value.match(/[^a-zA-Z0-9 \t\n\r]/)
// // },
// // message: (_, values) => i18nCallback.t('site.signup.special-char', values),
// // })
// //
// // defineRule('noWhitespaceCharacters', {
// // validate(value) {
// // return !value.match(/[ \t\n\r]+/)
// // },
// // message: (_, values) => i18nCallback.t('site.signup.no-whitespace', values),
// // })
// //
// // defineRule('samePassword', {
// // validate(value, [pwd]) {
// // return value === pwd
// // },
// // message: (_, values) => i18nCallback.t('site.signup.dont_match', values),
// // })
// //
// // defineRule('usernameAllowedChars', {
// // validate(value) {
// // return !!value.match(/^[a-zA-Z0-9_-]+$/)
// // },
// // message: (_, values) => i18nCallback.t('form.validation.username-allowed-chars', values),
// // })
// //
// // defineRule('usernameHyphens', {
// // validate(value) {
// // return !!value.match(/^[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+?)*$/)
// // },
// // message: (_, values) => i18nCallback.t('form.validation.username-hyphens', values),
// // })
// //
// // defineRule('usernameUnique', {
// // validate(value) {
// // if (!value.match(USERNAME_REGEX)) return true
// // return apollo
// // .query({
// // query: checkUsername,
// // variables: { username: value },
// // })
// // .then(({ data }) => {
// // return {
// // valid: data.checkUsername,
// // }
// // })
// // },
// // message: (_, values) => i18nCallback.t('form.validation.username-unique', values),
// // })
// //
// // defineRule('validIdentifier', {
// // validate(value) {
// // const isEmail = !!EMAIL_REGEX.test(value)
// // const isUsername = !!value.match(USERNAME_REGEX)
// // const isGradidoId = validateUuid(value) && versionUuid(value) === 4
// // return isEmail || isUsername || isGradidoId
// // },
// // message: (_, values) => i18nCallback.t('form.validation.valid-identifier', values),
// // })
// }
import { configure, defineRule } from 'vee-validate'
import { required, email, min, max } from '@vee-validate/rules'
import { checkUsername } from '@/graphql/queries'
@ -256,7 +76,7 @@ export const loadAllRules = (i18nCallback, apollo) => {
return !!value.match(/.{8,}/) || i18nCallback.t('site.signup.minimum')
})
defineRule('atLeastOneSpecialCharater', (value) => {
defineRule('atLeastOneSpecialCharacter', (value) => {
return !!value.match(/[^a-zA-Z0-9 \t\n\r]/) || i18nCallback.t('site.signup.special-char')
})
@ -264,8 +84,8 @@ export const loadAllRules = (i18nCallback, apollo) => {
return !value.match(/[ \t\n\r]+/) || i18nCallback.t('site.signup.no-whitespace')
})
defineRule('samePassword', (value, [pwd]) => {
return value === pwd || i18nCallback.t('site.signup.dont_match')
defineRule('samePassword', (value, [pwd], ctx) => {
return value === ctx.form[pwd] || i18nCallback.t('site.signup.dont_match')
})
defineRule('usernameAllowedChars', (value) => {