fix(frontend): WiP migration

This commit is contained in:
Mateusz Michałowski 2024-08-02 12:42:04 +02:00
parent 4879f3c3a8
commit 71bf1c7e0d
39 changed files with 1771 additions and 888 deletions

View File

@ -18,9 +18,11 @@
"@babel/core": "^7.13.13",
"@babel/node": "^7.13.13",
"@babel/preset-env": "^7.13.12",
"@vee-validate/i18n": "^4.13.2",
"@vee-validate/rules": "^4.13.2",
"@vee-validate/yup": "^4.13.2",
"@vitejs/plugin-vue": "3.2.0",
"@vue/apollo-composable": "^4.0.2",
"@vue/apollo-option": "^4.0.0",
"@vue/compat": "^3.4.31",
"@vue/test-utils": "^1.1.3",
@ -47,7 +49,8 @@
"express": "^4.17.1",
"flatpickr": "^4.5.7",
"flush-promises": "^1.0.2",
"graphql": "^15.5.1",
"graphql": "^16.9.0",
"graphql-tag": "^2.12.6",
"identity-obj-proxy": "^3.0.0",
"jest": "^26.6.3",
"jest-canvas-mock": "^2.5.0",
@ -68,6 +71,7 @@
"vue-jest": "^3.0.7",
"vue-loading-overlay": "^3.4.2",
"vue-router": "^4.4.0",
"vue-timer-hook": "^1.0.84",
"vue-timers": "^2.0.4",
"vue2-transitions": "^0.2.3",
"vuex": "^4.1.0",
@ -76,7 +80,9 @@
},
"devDependencies": {
"@apollo/client": "^3.10.8",
"@iconify-json/bi": "^1.1.23",
"@intlify/eslint-plugin-vue-i18n": "^1.4.0",
"@vue/compiler-sfc": "^3.4.35",
"@vue/eslint-config-prettier": "^4.0.1",
"babel-plugin-component": "^1.1.0",
"babel-plugin-transform-require-context": "^0.1.1",
@ -90,6 +96,7 @@
"stylelint": "^14.5.3",
"stylelint-config-recommended-vue": "^1.3.0",
"stylelint-config-standard-scss": "^3.0.0",
"unplugin-icons": "^0.19.1",
"unplugin-vue-components": "^0.27.3",
"vue-html-webpack-plugin": "^3.2.2"
},

View File

@ -1,5 +1,6 @@
<template>
<div id="app" ref="app" :class="darkMode ? 'dark-mode' : ''">
<BToastOrchestrator />
<div :class="$route.meta.requiresAuth ? 'appContent' : ''">
<component :is="$route.meta.requiresAuth ? 'DashboardLayout' : 'AuthLayout'" />
<div class="goldrand position-fixed fixed-bottom zindex1000"></div>

View File

@ -64,18 +64,18 @@ a:hover,
}
.btn-gradido {
display: inline-block;
padding: 0.6em 3em;
display: inline-block !important;
padding: 0.6em 3em !important;
letter-spacing: 0.05em;
color: #fff;
transition: all 0.5s ease;
color: #fff !important;
transition: all 0.5s ease !important;
background: rgb(249 205 105);
background: linear-gradient(135deg, rgb(249 205 105 / 100%) 2%, rgb(197 141 56 / 100%) 55%);
box-shadow: rgb(0 0 0 / 40%) 0 30px 90px;
border-radius: 26px;
padding-right: 50px;
padding-left: 50px;
border-style: none;
border-radius: 26px !important;
padding-right: 50px !important;
padding-left: 50px !important;
border-style: none !important;
}
.btn-gradido:hover {
@ -88,17 +88,17 @@ a:hover,
}
.btn-gradido-disable {
padding: 0.6em 3em;
padding: 0.6em 3em !important;
letter-spacing: 0.05em;
color: #fff;
transition: all 0.5s ease;
color: #fff !important;
transition: all 0.5s ease !important;
background: rgb(97 97 97);
background: linear-gradient(135deg, rgb(180 180 180 / 100%) 46%, rgb(180 180 180 / 100%) 99%);
box-shadow: rgb(0 0 0 / 40%) 0 30px 90px;
border-radius: 26px;
padding-right: 50px;
padding-left: 50px;
border-style: none;
border-radius: 26px !important;
padding-right: 50px !important;
padding-left: 50px !important;
border-style: none !important;
}
.btn-gradido-disable:hover {

View File

@ -54,5 +54,6 @@
// Bootstrap-vue (2.21.1) scss
//@import "bootstrap-vue/src/index";
@import "custom/variables";
@import "gradido-template";
@import "gradido-template-dark";

View File

@ -1,7 +1,7 @@
<template>
<footer class="footer m-4 p-4 bg-transparent">
<b-row align-v="center" class="mt-4 justify-content-lg-between">
<b-col>
<BRow align-v="center" class="mt-4 justify-content-lg-between">
<BCol>
<div class="copyright text-center text-lg-center text-muted">
{{ $t('footer.copyright.year', { year }) }}
<a
@ -23,18 +23,18 @@
{{ $t('footer.short_hash', { shortHash }) }}
</a>
</div>
</b-col>
</b-row>
<b-row align-v="center" class="justify-content-lg-between">
<b-col>
<b-nav class="nav-footer justify-content-center">
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/impressum/`" target="_blank">
</BCol>
</BRow>
<BRow align-v="center" class="justify-content-lg-between">
<BCol>
<BNav class="nav-footer justify-content-center">
<BNavItem :href="`https://gradido.net/${$i18n.locale}/impressum/`" target="_blank">
{{ $t('footer.imprint') }}
</b-nav-item>
<b-nav-item :href="`https://gradido.net/${$i18n.locale}/datenschutz/`" target="_blank">
</BNavItem>
<BNavItem :href="`https://gradido.net/${$i18n.locale}/datenschutz/`" target="_blank">
{{ $t('footer.privacy_policy') }}
</b-nav-item>
<b-nav-item
</BNavItem>
<BNavItem
:href="
$i18n.locale === 'de'
? 'https://docs.google.com/document/d/1jZp-DiiMPI9ZPNXmjsvOQ1BtnfDFfx8BX7CDmA8KKjY/edit?usp=sharing'
@ -43,13 +43,13 @@
target="_blank"
>
{{ $t('footer.whitepaper') }}
</b-nav-item>
<b-nav-item :href="`mailto:${supportEmail}`" target="_blank">
</BNavItem>
<BNavItem :href="`mailto:${supportEmail}`" target="_blank">
{{ $t('navigation.support') }}
</b-nav-item>
</b-nav>
</b-col>
</b-row>
</BNavItem>
</BNav>
</BCol>
</BRow>
</footer>
</template>
<script>

View File

@ -4,9 +4,9 @@
<div v-if="transactionGdtCount === 0" class="text-center">
{{ $t('gdt.no-transactions') }}
<hr />
<b-button class="gdt-funding" :href="link" target="_blank">
<BButton class="gdt-funding" :href="link" target="_blank">
{{ $t('gdt.funding') }}
</b-button>
</BButton>
</div>
<div v-else-if="transactionGdtCount === -1" class="text-center">
{{ $t('gdt.not-reachable') }}
@ -27,7 +27,7 @@
></transaction>
</div>
</div>
<b-pagination
<BPagination
v-if="transactionGdtCount > pageSize"
class="mt-3"
pills
@ -37,7 +37,7 @@
:total-rows="transactionGdtCount"
align="center"
:hide-ellipsis="true"
></b-pagination>
/>
</div>
</template>

View File

@ -36,6 +36,7 @@
:model-value="value"
@update:modelValue="normalizeEmail($event)"
v-bind="ariaInput"
:state="meta.valid"
data-test="input-email"
:id="labelFor"
:name="name"
@ -105,6 +106,7 @@
import { ref, watch, 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],
@ -118,15 +120,15 @@ import { useI18n } from 'vue-i18n'
const props = defineProps({
name: {
type: String,
required: true,
default: 'email',
},
label: {
type: String,
required: true,
default: 'Email',
},
placeholder: {
type: String,
required: true,
default: 'Email',
},
disabled: {
type: Boolean,
@ -137,7 +139,7 @@ const props = defineProps({
const emit = defineEmits(['onValidation'])
// Use the useField hook for validation
const { value, errorMessage, errors, meta } = useField(() => props.name)
const { value, errorMessage, errors, validate, meta } = useField(() => props.name, 'required|email')
const { t } = useI18n()
@ -152,6 +154,7 @@ const normalizeEmail = (emailAddress) => {
//TODO trigger blur on bootstrap input
// emailFocused.value = false
value.value = emailAddress.trim()
validate()
}
// Computed properties for ARIA attributes and labelFor

View File

@ -56,7 +56,7 @@
:name="name"
:placeholder="defaultTranslations.placeholder"
:type="showPassword ? 'text' : 'password'"
:state="validated ? valid : false"
:state="meta.valid"
data-test="password-input-field"
v-bind="ariaInput"
/>
@ -67,21 +67,20 @@
class="border-left-0 rounded-right"
tabindex="-1"
>
{{ showPassword ? 'eye' : 'eye-slash' }}
<IBiEye v-if="showPassword" />
<IBiEyeSlash v-else />
</BButton>
</template>
<BFormInvalidFeedback v-bind="ariaMsg">
<!-- <div v-if="showAllErrors">-->
<!-- <span v-for="error in errors" :key="error">-->
<!-- {{ error }}-->
<!-- <br />-->
<!-- </span>-->
<!-- </div>-->
<div>
{{ error }}
</div>
</BFormInvalidFeedback>
</BInputGroup>
<BFormInvalidFeedback v-bind="ariaMsg">
<!-- <div v-if="showAllErrors">-->
<!-- <span v-for="error in errors" :key="error">-->
<!-- {{ error }}-->
<!-- <br />-->
<!-- </span>-->
<!-- </div>-->
{{ errorMessage }}
</BFormInvalidFeedback>
</BFormGroup>
</div>
</template>
@ -128,7 +127,7 @@
<!--</script>-->
<script setup>
import { ref, computed, watch, defineProps, defineEmits } from 'vue'
import { ref, computed, watch, defineProps, defineEmits, toRef } from 'vue'
import { useField } from 'vee-validate'
import { useI18n } from 'vue-i18n'
@ -162,8 +161,9 @@ const props = defineProps({
const emit = defineEmits(['update:modelValue'])
const name = toRef(props, 'name')
// Use the useField hook for validation
const { value, errorMessage, valid, validated, meta } = useField(() => props.name)
const { value, errorMessage, meta } = useField(name, 'required')
const { t } = useI18n()
@ -182,7 +182,7 @@ const toggleShowPassword = () => {
// Computed properties for ARIA attributes and labelFor
const ariaInput = computed(() => ({
'aria-invalid': valid ? false : 'true',
'aria-invalid': meta.valid ? false : 'true',
'aria-describedby': `${props.name}-feedback`,
}))

View File

@ -11,7 +11,8 @@
{{ lang.name }}
</span>
</span>
<b-icon icon="caret-down-fill" aria-hidden="true"></b-icon>
<!-- <b-icon icon="caret-down-fill" aria-hidden="true"></b-icon>-->
<IBiCaretDownFill />
</div>
<BCollapse id="collapse-1" class="mt-4">
<span
@ -39,74 +40,148 @@
</div>
</template>
<script>
import locales from '@/locales/'
import { updateUserInfos } from '@/graphql/mutations'
<!--<script>-->
<!--import locales from '@/locales/'-->
<!--import { updateUserInfos } from '@/graphql/mutations'-->
export default {
name: 'LanguageSwitch',
data() {
return {
locales: locales,
currentLanguage: {},
}
},
methods: {
setLocale(locale) {
this.$store.commit('language', locale)
this.currentLanguage = this.getLocaleObject(locale)
},
async saveLocale(locale) {
if (this.$i18n.locale === locale) return
this.setLocale(locale)
if (this.$store.state.gradidoID) {
this.$apollo
.mutate({
mutation: updateUserInfos,
variables: {
locale: locale,
},
})
.then(() => {
this.toastSuccess(this.$t('settings.language.success'))
})
.catch(() => {
this.toastSuccess(this.$t('error'))
})
}
},
getLocaleObject(code) {
return this.locales.find((l) => l.code === code)
},
getNavigatorLanguage() {
const lang = navigator.language
if (lang) return lang.split('-')[0]
return lang
},
setCurrentLanguage() {
let locale = this.$store.state.language || this.getNavigatorLanguage() || 'en'
let object = this.getLocaleObject(locale)
if (!object) {
locale = 'en'
object = this.getLocaleObject(locale)
}
this.setLocale(locale)
this.currentLanguage = object
},
},
computed: {
indexOfSelectedLocale() {
return this.locales.findIndex((element) => element.code === this.$store.state.language)
},
indexOfSecondLastLocale() {
return this.locales.length - 2
},
indexOfLastLocale() {
return this.locales.length - 1
},
},
created() {
this.setCurrentLanguage()
},
<!--export default {-->
<!-- name: 'LanguageSwitch',-->
<!-- data() {-->
<!-- return {-->
<!-- locales: locales,-->
<!-- currentLanguage: {},-->
<!-- }-->
<!-- },-->
<!-- methods: {-->
<!-- setLocale(locale) {-->
<!-- this.$store.commit('language', locale)-->
<!-- this.currentLanguage = this.getLocaleObject(locale)-->
<!-- },-->
<!-- async saveLocale(locale) {-->
<!-- if (this.$i18n.locale === locale) return-->
<!-- this.setLocale(locale)-->
<!-- if (this.$store.state.gradidoID) {-->
<!-- this.$apollo-->
<!-- .mutate({-->
<!-- mutation: updateUserInfos,-->
<!-- variables: {-->
<!-- locale: locale,-->
<!-- },-->
<!-- })-->
<!-- .then(() => {-->
<!-- this.toastSuccess(this.$t('settings.language.success'))-->
<!-- })-->
<!-- .catch(() => {-->
<!-- this.toastSuccess(this.$t('error'))-->
<!-- })-->
<!-- }-->
<!-- },-->
<!-- getLocaleObject(code) {-->
<!-- return this.locales.find((l) => l.code === code)-->
<!-- },-->
<!-- getNavigatorLanguage() {-->
<!-- const lang = navigator.language-->
<!-- if (lang) return lang.split('-')[0]-->
<!-- return lang-->
<!-- },-->
<!-- setCurrentLanguage() {-->
<!-- let locale = this.$store.state.language || this.getNavigatorLanguage() || 'en'-->
<!-- let object = this.getLocaleObject(locale)-->
<!-- if (!object) {-->
<!-- locale = 'en'-->
<!-- object = this.getLocaleObject(locale)-->
<!-- }-->
<!-- this.setLocale(locale)-->
<!-- this.currentLanguage = object-->
<!-- },-->
<!-- },-->
<!-- computed: {-->
<!-- indexOfSelectedLocale() {-->
<!-- return this.locales.findIndex((element) => element.code === this.$store.state.language)-->
<!-- },-->
<!-- indexOfSecondLastLocale() {-->
<!-- return this.locales.length - 2-->
<!-- },-->
<!-- indexOfLastLocale() {-->
<!-- return this.locales.length - 1-->
<!-- },-->
<!-- },-->
<!-- created() {-->
<!-- this.setCurrentLanguage()-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { useStore } from 'vuex'
import { useI18n } from 'vue-i18n'
import { useMutation } from '@vue/apollo-composable'
import { useAppToast } from '../composables/useToast'
import locales from '@/locales/'
import { onMounted, ref, computed } from 'vue'
import { updateUserInfos } from '../graphql/mutations'
const store = useStore()
const { t, locale } = useI18n()
const { mutate } = useMutation(updateUserInfos)
const { toastSuccess, toastError } = useAppToast()
const currentLang = ref({})
const getLocaleObject = (localeCode) => {
return locales.find((lang) => lang.code === localeCode)
}
const setLocale = (newLocale) => {
store.commit('language', newLocale)
currentLang.value = getLocaleObject(newLocale)
}
const saveLocale = async (newLocale) => {
if (locale.value === newLocale) return
setLocale(newLocale)
if (store.state.gradidoID) {
try {
await mutate({ locale: newLocale })
toastSuccess(t('settings.language.success'))
} catch (error) {
toastError(t('settings.language.error'))
}
}
}
const getNavigatorLang = () => {
const navigatorLang = navigator.language
if (navigatorLang) return navigatorLang.split('-')[0]
return navigatorLang
}
const setCurrentLanguage = () => {
let newLocale = store.state.language || getNavigatorLang() || 'en'
let langObject = getLocaleObject(newLocale)
if (!langObject) {
newLocale = 'en'
langObject = getLocaleObject(newLocale)
}
setLocale(newLocale)
currentLang.value = langObject
}
const indexOfSelectedLocale = computed(() => {
return locales.findIndex((element) => element.code === store.state.language)
})
const indexOfSecondLastLocale = computed(() => {
return locales.length - 2
})
const indexOfLastLocale = computed(() => {
return locales.length - 1
})
onMounted(() => {
setCurrentLanguage()
})
</script>

View File

@ -7,51 +7,51 @@
:class="shadow ? 'appBoxShadow' : ''"
>
<div class="mb-3 mt-3">
<b-nav vertical class="w-200">
<b-nav-item to="/overview" class="mb-3" active-class="activeRoute">
<b-img src="/img/svg/home.svg" height="20" class="svg-icon" />
<BNav vertical class="w-200">
<BNavItem to="/overview" class="mb-3" active-class="activeRoute">
<BImg src="/img/svg/home.svg" height="20" class="svg-icon" />
<span class="ml-2">{{ $t('navigation.overview') }}</span>
</b-nav-item>
<b-nav-item to="/send" class="mb-3" active-class="activeRoute">
</BNavItem>
<BNavItem to="/send" class="mb-3" active-class="activeRoute">
<b-icon icon="cash" aria-hidden="true"></b-icon>
<span class="ml-2">{{ $t('navigation.send') }}</span>
</b-nav-item>
<b-nav-item to="/transactions" :class="transactionClass" active-class="activeRoute">
<b-img src="/img/svg/transaction.svg" height="20" class="svg-icon" />
</BNavItem>
<BNavItem to="/transactions" :class="transactionClass" active-class="activeRoute">
<BImg src="/img/svg/transaction.svg" height="20" class="svg-icon" />
<span class="ml-2">{{ $t('navigation.transactions') }}</span>
</b-nav-item>
<b-nav-item to="/community" class="mb-3" active-class="activeRoute">
<b-img src="/img/svg/community.svg" height="20" class="svg-icon" />
</BNavItem>
<BNavItem to="/community" class="mb-3" active-class="activeRoute">
<BImg src="/img/svg/community.svg" height="20" class="svg-icon" />
<span class="ml-2">{{ $t('creation') }}</span>
</b-nav-item>
<b-nav-item to="/information" class="mb-3" active-class="activeRoute">
<b-img src="/img/svg/info.svg" height="20" class="svg-icon" />
</BNavItem>
<BNavItem to="/information" class="mb-3" active-class="activeRoute">
<BImg src="/img/svg/info.svg" height="20" class="svg-icon" />
<span class="ml-2">{{ $t('navigation.info') }}</span>
</b-nav-item>
<b-nav-item to="/circles" v-if="isHumhub" class="mb-3" active-class="activeRoute">
<b-img src="/img/svg/circles.svg" height="20" class="svg-icon" />
</BNavItem>
<BNavItem to="/circles" v-if="isHumhub" class="mb-3" active-class="activeRoute">
<BImg src="/img/svg/circles.svg" height="20" class="svg-icon" />
<span class="ml-2">{{ $t('navigation.circles') }}</span>
</b-nav-item>
<b-nav-item to="/usersearch" v-if="isGMS" active-class="activeRoute">
<b-img src="/img/loupe.png" height="20" />
</BNavItem>
<BNavItem to="/usersearch" v-if="isGMS" active-class="activeRoute">
<BImg src="/img/loupe.png" height="20" />
<span class="ml-2">{{ $t('navigation.usersearch') }}</span>
</b-nav-item>
</b-nav>
</BNavItem>
</BNav>
<hr class="m-3" />
<b-nav vertical class="w-100">
<b-nav-item
<BNav vertical class="w-100">
<BNavItem
to="/settings"
class="mb-3"
active-class="activeRoute"
data-test="settings-menu"
>
<b-img src="/img/svg/settings.svg" height="20" class="svg-icon" />
<BImg src="/img/svg/settings.svg" height="20" class="svg-icon" />
<span class="ml-2">{{ $t('navigation.settings') }}</span>
<b-badge v-if="!$store.state.username" variant="warning">
<BBadge v-if="!$store.state.username" variant="warning">
{{ $t('settings.newSettings') }}
</b-badge>
</b-nav-item>
<b-nav-item
</BBadge>
</BNavItem>
<BNavItem
class="mb-3 text-light"
v-if="$store.state.roles && $store.state.roles.length > 0"
@click="$emit('admin')"
@ -61,17 +61,17 @@
<span class="ml-2">
{{ $t('navigation.admin_area') }}
</span>
</b-nav-item>
<b-nav-item
</BNavItem>
<BNavItem
class="font-weight-bold"
@click="$emit('logout')"
active-class="activeRoute"
data-test="logout-menu"
>
<b-img src="/img/svg/logout.svg" height="20" class="svg-icon" />
<BImg src="/img/svg/logout.svg" height="20" class="svg-icon" />
<span class="ml-2 text-205">{{ $t('navigation.logout') }}</span>
</b-nav-item>
</b-nav>
</BNavItem>
</BNav>
</div>
</div>
</div>

View File

@ -1,17 +1,17 @@
<template>
<div class="community-news">
<div v-for="item in News" :key="item.locale">
<b-card
<BCard
v-if="item.locale === $i18n.locale"
class="bg-white appBoxShadow gradido-border-radius"
>
<b-card-body>
<b-card-title class="h2">{{ item.text }}</b-card-title>
<BCardBody>
<BCardTitle class="h2">{{ item.text }}</BCardTitle>
<div class="h3">{{ item.date }}</div>
<b-row class="my-5">
<b-col>
<BRow class="my-5">
<BCol>
{{ item.extra }}
<br />
<br />
@ -21,25 +21,25 @@
<span v-if="item.email">
<a :href="'mailto:' + item.email">{{ item.email }}</a>
</span>
</b-col>
</b-row>
</BCol>
</BRow>
<b-row class="my-5">
<b-col cols="12">
<BRow class="my-5">
<BCol cols="12">
<div class="text-lg-right">
<b-button v-if="item.url" variant="gradido" :href="item.url" target="_blank">
<BButton v-if="item.url" variant="gradido" :href="item.url" target="_blank">
{{ item.button }}
</b-button>
</BButton>
<RouterLink v-else-if="item.internUrl" to="/settings/extern">
<b-button variant="gradido">
<BButton variant="gradido">
{{ item.button }}
</b-button>
</BButton>
</RouterLink>
</div>
</b-col>
</b-row>
</b-card-body>
</b-card>
</BCol>
</BRow>
</BCardBody>
</BCard>
</div>
</div>
</template>

View File

@ -1,6 +1,6 @@
<template>
<div class="session-logout-timeout">
<b-modal
<BModal
id="modalSessionTimeOut"
class="bg-variant-danger"
hide-header-close
@ -8,8 +8,8 @@
hide-footer
no-close-on-backdrop
>
<b-card header-tag="header" footer-tag="footer">
<b-card-text>
<BCard header-tag="header" footer-tag="footer">
<BCardText>
<div class="p-3 h2">{{ $t('session.warningText') }}</div>
<div class="p-3">
{{ $t('session.lightText') }}
@ -19,85 +19,152 @@
<b>{{ tokenExpiresInSeconds }}</b>
{{ $t('time.seconds') }}
</div>
</b-card-text>
<b-row>
<b-col class="text-center">
<b-button size="lg" variant="success" @click="handleOk">
</BCardText>
<BRow>
<BCol class="text-center">
<BButton size="lg" variant="success" @click="handleOk">
{{ $t('session.extend') }}
</b-button>
</b-col>
</b-row>
</b-card>
</BButton>
</BCol>
</BRow>
</BCard>
<template #modal-footer>
<b-button size="sm" variant="danger" @click="$emit('logout')">
<BButton size="sm" variant="danger" @click="$emit('logout')">
{{ $t('navigation.logout') }}
</b-button>
<b-button size="lg" variant="success" @click="handleOk">
</BButton>
<BButton size="lg" variant="success" @click="handleOk">
{{ $t('session.extend') }}
</b-button>
</BButton>
</template>
</b-modal>
</BModal>
</div>
</template>
<script>
<!--<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 { 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'
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')
},
}
const store = useStore()
const { result, load: verifyLoginQuery } = useLazyQuery(verifyLogin)
const { modal } = useModal()
const timer = useTimer()
console.log(timer)
const emit = defineEmits(['logout'])
const now = ref(new Date().getTime())
const tokenExpiresInSeconds = computed(() => {
const remainingSecs = Math.floor(
(new Date(store.state.tokenTime * 1000).getTime() - now.value) / 1000,
)
return remainingSecs <= 0 ? 0 : remainingSecs
})
// 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')
// })
</script>

View File

@ -1,23 +1,23 @@
<template>
<div class="community-member mt-3 mt-lg-0">
<div class="text-center bg-gradient">
<b-badge class="position-absolute mt--2 ml--5 px-3 bg-gradient">
<BBadge class="position-absolute mt--2 ml--5 px-3 bg-gradient">
{{ $t('member') }}
</b-badge>
</BBadge>
</div>
<div
class="community-member bg-white appBoxShadow gradido-border-radius p-4 border border-success"
>
<b-row>
<b-col cols="9">
<BRow>
<BCol cols="9">
<div class="h4">{{ $t('community.communityMember') }}</div>
<div>{{ CONFIG.COMMUNITY_NAME }}</div>
</b-col>
<b-col cols="3" align-self="end" class="border-left border-light">
<b-icon icon="people"></b-icon>
</BCol>
<BCol cols="3" align-self="end" class="border-left border-light">
<IBiPeople />
{{ totalUsers }}
</b-col>
</b-row>
</BCol>
</BRow>
</div>
</div>
</template>

View File

@ -1,14 +1,14 @@
<template>
<div class="gdd-amount translucent-color-opacity">
<div class="text-center">
<b-badge
<BBadge
v-if="badgeShow"
class="position-absolute mt--2 ml--4 px-3 zindex1"
:class="showStatus ? 'bg-gradient' : ''"
:variant="showStatus ? '' : 'light'"
>
{{ $t('GDD') }}
</b-badge>
</BBadge>
</div>
<div
class="wallet-amount bg-white appBoxShadow gradido-border-radius p-4 border"
@ -18,71 +18,118 @@
: 'border-light opacity-05'
"
>
<b-row>
<b-col class="h4">{{ $t('gddKonto') }}</b-col>
</b-row>
<BRow>
<BCol class="h4">{{ $t('gddKonto') }}</BCol>
</BRow>
<b-row>
<b-col cols="9">
<b-icon
icon="layers"
class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"
></b-icon>
<BRow>
<BCol cols="9">
<!-- <b-icon-->
<!-- icon="layers"-->
<!-- class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"-->
<!-- ></b-icon>-->
<IBiLayers />
<span v-if="hideAmount" class="font-weight-bold gradido-global-color-accent">
{{ $t('asterisks') }}
</span>
<span v-else class="font-weight-bold gradido-global-color-accent">
{{ balance | GDD }}
<!-- {{ balance | GDD }}-->
{{ 'test' }}
</span>
</b-col>
<b-col 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>
</b-col>
</b-row>
</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 @click="updateHideAmountGDD">
<IBiEyeSlash v-if="hideAmount" />
<IBiEye v-else />
</button>
</BCol>
</BRow>
</div>
</div>
</template>
<script>
import { updateUserInfos } from '@/graphql/mutations'
<!--<script>-->
<!--import { updateUserInfos } from '@/graphql/mutations'-->
export default {
name: 'GddAmount',
props: {
path: { type: String, required: false, default: '' },
balance: { type: Number, required: true },
badgeShow: { type: Boolean, default: true },
showStatus: { type: Boolean, default: false },
},
computed: {
hideAmount() {
return this.$store.state.hideAmountGDD
},
},
methods: {
async updateHideAmountGDD() {
this.$apollo
.mutate({
mutation: updateUserInfos,
variables: {
hideAmountGDD: !this.hideAmount,
},
})
.then(() => {
this.$store.commit('hideAmountGDD', !this.hideAmount)
if (!this.hideAmount) {
this.toastSuccess(this.$t('settings.showAmountGDD'))
} else {
this.toastSuccess(this.$t('settings.hideAmountGDD'))
}
})
.catch((error) => {
this.toastError(error.message)
})
},
},
<!--export default {-->
<!-- name: 'GddAmount',-->
<!-- props: {-->
<!-- path: { type: String, required: false, default: '' },-->
<!-- balance: { type: Number, required: true },-->
<!-- badgeShow: { type: Boolean, default: true },-->
<!-- showStatus: { type: Boolean, default: false },-->
<!-- },-->
<!-- computed: {-->
<!-- hideAmount() {-->
<!-- return this.$store.state.hideAmountGDD-->
<!-- },-->
<!-- },-->
<!-- methods: {-->
<!-- async updateHideAmountGDD() {-->
<!-- this.$apollo-->
<!-- .mutate({-->
<!-- mutation: updateUserInfos,-->
<!-- variables: {-->
<!-- hideAmountGDD: !this.hideAmount,-->
<!-- },-->
<!-- })-->
<!-- .then(() => {-->
<!-- this.$store.commit('hideAmountGDD', !this.hideAmount)-->
<!-- if (!this.hideAmount) {-->
<!-- this.toastSuccess(this.$t('settings.showAmountGDD'))-->
<!-- } else {-->
<!-- this.toastSuccess(this.$t('settings.hideAmountGDD'))-->
<!-- }-->
<!-- })-->
<!-- .catch((error) => {-->
<!-- this.toastError(error.message)-->
<!-- })-->
<!-- },-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { computed } from 'vue'
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'
const props = defineProps({
path: { type: String, required: false, default: '' },
balance: { type: Number, required: true },
badgeShow: { type: Boolean, default: true },
showStatus: { type: Boolean, default: false },
})
const store = useStore()
const { mutate } = useMutation(updateUserInfos)
const { t } = useI18n()
const { toastSuccess, toastError } = useAppToast()
const hideAmount = computed(() => store.state.hideAmountGDD)
const updateHideAmountGDD = async () => {
try {
await mutate({
hideAmountGDD: !hideAmount.value,
})
store.commit('hideAmountGDD', !hideAmount.value)
if (!hideAmount.value) {
toastSuccess(t('settings.showAmountGDD'))
} else {
toastSuccess(t('settings.hideAmountGDD'))
}
} catch (error) {
toastError(error.message)
}
}
</script>

View File

@ -1,82 +1,127 @@
<template>
<div class="gdt-amount mt-3 mt-lg-0">
<div class="text-center">
<b-badge
<BBadge
v-if="badgeShow"
class="position-absolute mt--2 ml--4 px-3 zindex1"
:class="showStatus ? 'bg-gradient' : ''"
:variant="showStatus ? '' : 'light'"
>
{{ $t('GDT') }}
</b-badge>
</BBadge>
</div>
<div
class="wallet-amount bg-white appBoxShadow gradido-border-radius p-4 border"
:class="showStatus ? 'gradido-global-border-color-accent' : 'border-light opacity-05'"
>
<b-row>
<b-col class="h4">{{ $t('gdt.gdtKonto') }}</b-col>
</b-row>
<b-row>
<b-col cols="9">
<b-icon
icon="layers"
class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"
></b-icon>
<BRow>
<BCol class="h4">{{ $t('gdt.gdtKonto') }}</BCol>
</BRow>
<BRow>
<BCol cols="9">
<!-- <b-icon-->
<!-- icon="layers"-->
<!-- class="mr-3 gradido-global-border-color-accent d-none d-lg-inline"-->
<!-- ></b-icon>-->
<IBiLayers />
<span v-if="hideAmount" class="font-weight-bold gradido-global-color-accent">
{{ $t('asterisks') }}
</span>
<span v-else class="font-weight-bold gradido-global-color-accent">
{{ $n(GdtBalance, 'decimal') }} {{ $t('GDT') }}
</span>
</b-col>
<b-col 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="updateHideAmountGDT"
></b-icon>
</b-col>
</b-row>
</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="updateHideAmountGDT"-->
<!-- ></b-icon>-->
<button @click="updateHideAmountGDT">
<IBiEyeSlash v-if="hideAmount" />
<IBiEye v-else />
</button>
</BCol>
</BRow>
</div>
</div>
</template>
<script>
import { updateUserInfos } from '@/graphql/mutations'
<!--<script>-->
<!--import { updateUserInfos } from '@/graphql/mutations'-->
export default {
name: 'GdtAmount',
props: {
GdtBalance: { type: Number, required: true },
badgeShow: { type: Boolean, default: true },
showStatus: { type: Boolean, default: false },
},
computed: {
hideAmount() {
return this.$store.state.hideAmountGDT
},
},
methods: {
async updateHideAmountGDT() {
this.$apollo
.mutate({
mutation: updateUserInfos,
variables: {
hideAmountGDT: !this.hideAmount,
},
})
.then(() => {
this.$store.commit('hideAmountGDT', !this.hideAmount)
if (!this.hideAmount) {
this.toastSuccess(this.$t('settings.showAmountGDT'))
} else {
this.toastSuccess(this.$t('settings.hideAmountGDT'))
}
})
.catch((error) => {
this.toastError(error.message)
})
},
},
<!--export default {-->
<!-- name: 'GdtAmount',-->
<!-- props: {-->
<!-- GdtBalance: { type: Number, required: true },-->
<!-- badgeShow: { type: Boolean, default: true },-->
<!-- showStatus: { type: Boolean, default: false },-->
<!-- },-->
<!-- computed: {-->
<!-- hideAmount() {-->
<!-- return this.$store.state.hideAmountGDT-->
<!-- },-->
<!-- },-->
<!-- methods: {-->
<!-- async updateHideAmountGDT() {-->
<!-- this.$apollo-->
<!-- .mutate({-->
<!-- mutation: updateUserInfos,-->
<!-- variables: {-->
<!-- hideAmountGDT: !this.hideAmount,-->
<!-- },-->
<!-- })-->
<!-- .then(() => {-->
<!-- this.$store.commit('hideAmountGDT', !this.hideAmount)-->
<!-- if (!this.hideAmount) {-->
<!-- this.toastSuccess(this.$t('settings.showAmountGDT'))-->
<!-- } else {-->
<!-- this.toastSuccess(this.$t('settings.hideAmountGDT'))-->
<!-- }-->
<!-- })-->
<!-- .catch((error) => {-->
<!-- this.toastError(error.message)-->
<!-- })-->
<!-- },-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { computed } from 'vue'
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'
const props = defineProps({
GdtBalance: { type: Number, required: true },
badgeShow: { type: Boolean, default: true },
showStatus: { type: Boolean, default: false },
})
const store = useStore()
const { mutate } = useMutation(updateUserInfos)
const { t } = useI18n()
const { toastSuccess, toastError } = useAppToast()
const hideAmount = computed(() => store.state.hideAmountGDT)
const updateHideAmountGDT = async () => {
try {
await mutate({
hideAmountGDT: !hideAmount.value,
})
store.commit('hideAmountGDT', !hideAmount.value)
if (!hideAmount.value) {
toastSuccess(t('settings.showAmountGDT'))
} else {
toastSuccess(t('settings.hideAmountGDT'))
}
} catch (error) {
toastError(error.message)
}
}
</script>

View File

@ -1,14 +1,14 @@
<template>
<div class="rightside-last-transactions d-none d-lg-block">
<b-row class="mb-3">
<b-col class="h3">{{ $t('transaction.lastTransactions') }}</b-col>
<!-- <b-col cols="1" class="text-right">
<BRow class="mb-3">
<BCol class="h3">{{ $t('transaction.lastTransactions') }}</BCol>
<!-- <BCol cols="1" class="text-right">
<b-icon icon="three-dots-vertical"></b-icon>
</b-col> -->
</b-row>
</BCol> -->
</BRow>
<div v-for="(transaction, index) in transactions" :key="transaction.id">
<b-row
<BRow
align-v="center"
v-if="
index <= 8 &&
@ -18,7 +18,7 @@
"
class="mb-4"
>
<b-col cols="auto">
<BCol cols="auto">
<div class="align-items-center">
<avatar
:size="72"
@ -27,10 +27,10 @@
:initials="`${transaction.linkedUser.firstName[0]}${transaction.linkedUser.lastName[0]}`"
></avatar>
</div>
</b-col>
<b-col class="p-1">
<b-row>
<b-col>
</BCol>
<BCol class="p-1">
<BRow>
<BCol>
<div class="font-weight-bold">
<name :linkedUser="transaction.linkedUser" fontColor="text-dark" />
</div>
@ -42,10 +42,10 @@
{{ $d(new Date(transaction.balanceDate), 'short') }}
</div>
</div>
</b-col>
</b-row>
</b-col>
</b-row>
</BCol>
</BRow>
</BCol>
</BRow>
</div>
</div>
</template>

View File

@ -2,9 +2,9 @@
<div class="name">
<div class="gdd-transaction-list-item-name">
<div v-if="linkedUser && linkedUser.gradidoID">
<b-link @click.stop="tunnelEmail" :class="fontColor">
<BLink @click.stop="tunnelEmail" :class="fontColor">
{{ itemText }}
</b-link>
</BLink>
</div>
<span v-else>{{ itemText }}</span>
</div>

View File

@ -0,0 +1,49 @@
import { useI18n } from 'vue-i18n'
import { useToast } from 'bootstrap-vue-next'
export function useAppToast() {
const { t } = useI18n()
const { show } = useToast()
const toastSuccess = (message) => {
toast(message, {
title: t('success'),
variant: 'success',
})
}
const toastError = (message) => {
toast(message, {
title: t('error'),
variant: 'danger',
})
}
const toastInfo = (message) => {
toast(message, {
title: t('navigation.info'),
variant: 'warning',
})
}
const toast = (message, options = {}) => {
if (message.replace) message = message.replace(/^GraphQL error: /, '')
options = {
solid: true,
toaster: 'b-toaster-top-right',
headerClass: 'gdd-toaster-title',
bodyClass: 'gdd-toaster-body',
toastClass: 'gdd-toaster',
...options,
body: message,
}
show({ props: { ...options } })
}
return {
toastSuccess,
toastError,
toastInfo,
toast,
}
}

View File

@ -7,7 +7,7 @@ export const loadFilters = (_i18n) => {
const amount = (value) => {
if (!value && value !== 0) return ''
return i18n.n(value.toString(), 'decimal').replace('-', ' ')
return i18n.global.n(value.toString(), 'decimal').replace('-', ' ')
}
const GDD = (value) => {

View File

@ -40,13 +40,13 @@
<BCard no-body ref="pageFontSize" class="border-0 mt-4 gradido-custom-background">
<BRow class="p-4">
<BCol cols="10">
<language-switch class="ml-3" />
<language-switch-2 class="ml-3" />
</BCol>
<BCol cols="2" class="text-right">
<div id="popover-target-1" class="pointer">
<BImg src="/img/svg/type.svg" width="19" class="svgType"></BImg>
</div>
<Bpopover
<BPopover
target="popover-target-1"
triggers="click"
placement="top"
@ -59,7 +59,7 @@
{{ $t('math.pipe') }}
<span class="pointer" @click="setTextSize(1.25)">{{ $t('125') }}</span>
</div>
</Bpopover>
</BPopover>
</BCol>
</BRow>
<BRow class="d-inline d-sm-inline d-md-none d-lg-none mb-3">
@ -92,7 +92,7 @@
import AuthNavbar from '@/components/Auth/AuthNavbar'
import AuthNavbarSmall from '@/components/Auth/AuthNavbarSmall'
import AuthCarousel from '@/components/Auth/AuthCarousel'
import LanguageSwitch from '@/components/LanguageSwitch2'
import LanguageSwitch2 from '@/components/LanguageSwitch2'
import AuthFooter from '@/components/Auth/AuthFooter'
import CONFIG from '@/config'
@ -102,7 +102,7 @@ export default {
AuthNavbar,
AuthNavbarSmall,
AuthCarousel,
LanguageSwitch,
LanguageSwitch2,
AuthFooter,
},
data() {
@ -112,7 +112,9 @@ export default {
},
methods: {
setTextSize(size) {
this.$refs.pageFontSize.style.fontSize = size + 'rem'
console.log(size)
console.log(this.$refs.pageFontSize)
this.$refs.pageFontSize.$el.style.fontSize = size + 'rem'
},
},
}

View File

@ -5,54 +5,55 @@
</div>
<div v-else class="mx-lg-0">
<!-- navbar -->
<b-row>
<b-col>
<BRow>
<BCol>
<navbar class="main-navbar" :balance="balance"></navbar>
</b-col>
</b-row>
<mobile-sidebar @admin="admin" @logout="logout" />
</BCol>
</BRow>
<!-- TODO mobile sidebar needs new component to be fixed-->
<!-- <mobile-sidebar @admin="admin" @logout="logout" />-->
<!-- Breadcrumb -->
<b-row class="breadcrumb">
<b-col cols="10" offset-lg="2">
<BRow class="breadcrumb">
<BCol cols="10" offset-lg="2">
<breadcrumb />
</b-col>
</b-row>
</BCol>
</BRow>
<b-row fluid class="d-flex">
<BRow fluid class="d-flex">
<!-- Sidebar left -->
<b-col cols="2" class="d-none d-lg-block">
<BCol cols="2" class="d-none d-lg-block">
<sidebar class="main-sidebar" @admin="admin" @logout="logout" />
</b-col>
</BCol>
<!-- ContentHeader && Content -->
<b-col>
<b-row class="px-lg-3">
<b-col cols="12">
<b-row class="d-lg-flex" cols="12">
<BCol>
<BRow class="px-lg-3">
<BCol cols="12">
<BRow class="d-lg-flex" cols="12">
<!-- ContentHeader -->
<b-col>
<BCol>
<content-header
:balance="balance"
:GdtBalance="GdtBalance"
:totalUsers="totalUsers"
>
<template #overview>
<b-row>
<b-col cols="12" lg="5">
<BRow>
<BCol cols="12" lg="5">
<div>
<gdd-amount :balance="balance" :showStatus="false" :badgeShow="false" />
</div>
</b-col>
<b-col cols="12" lg="7">
</BCol>
<BCol cols="12" lg="7">
<div>
<community-member :totalUsers="totalUsers" />
</div>
</b-col>
</b-row>
</BCol>
</BRow>
</template>
<template #send>
<b-row>
<b-col cols="12" lg="6">
<BRow>
<BCol cols="12" lg="6">
<div>
<gdd-amount
:balance="balance"
@ -61,44 +62,44 @@
:badgeShow="false"
/>
</div>
</b-col>
<b-col cols="12" lg="6">
</BCol>
<BCol cols="12" lg="6">
<div>
<router-link to="gdt">
<gdt-amount :GdtBalance="GdtBalance" :badgeShow="false" />
</router-link>
</div>
</b-col>
</b-row>
</BCol>
</BRow>
</template>
<template #transactions>
<b-row>
<b-col cols="12" lg="6">
<BRow>
<BCol cols="12" lg="6">
<div>
<router-link to="transactions">
<gdd-amount :balance="balance" :showStatus="true" />
</router-link>
</div>
</b-col>
<b-col cols="12" lg="6">
</BCol>
<BCol cols="12" lg="6">
<div>
<router-link to="gdt">
<gdt-amount :GdtBalance="GdtBalance" />
</router-link>
</div>
</b-col>
</b-row>
</BCol>
</BRow>
</template>
<template #gdt>
<b-row>
<b-col cols="12" lg="6">
<BRow>
<BCol cols="12" lg="6">
<div>
<router-link to="transactions">
<gdd-amount :balance="balance" :showStatus="false" />
</router-link>
</div>
</b-col>
<b-col cols="12" lg="6">
</BCol>
<BCol cols="12" lg="6">
<div>
<router-link to="gdt">
<gdt-amount
@ -108,19 +109,19 @@
/>
</router-link>
</div>
</b-col>
</b-row>
</BCol>
</BRow>
</template>
<template #community>
<nav-community />
</template>
<template #settings></template>
</content-header>
</b-col>
</b-row>
</b-col>
</BCol>
</BRow>
</BCol>
<!-- Right Side Mobil -->
<b-col class="d-block d-lg-none">
<BCol class="d-block d-lg-none">
<right-side>
<template #transactions>
<last-transactions
@ -134,8 +135,8 @@
</template>
<template #empty />
</right-side>
</b-col>
<b-col cols="12">
</BCol>
<BCol cols="12">
<!-- router-view -->
<div class="main-content mt-lg-3 mt-0">
<fade-transition :duration="200" origin="center top" mode="out-in">
@ -151,11 +152,11 @@
></router-view>
</fade-transition>
</div>
</b-col>
</b-row>
</b-col>
</BCol>
</BRow>
</BCol>
<!-- RightSide Desktop -->
<b-col cols="3" class="d-none d-lg-block">
<BCol cols="3" class="d-none d-lg-block">
<right-side>
<template #transactions>
<last-transactions
@ -169,19 +170,158 @@
<community-template />
</template>
</right-side>
</b-col>
</b-row>
<b-row>
</BCol>
</BRow>
<BRow>
<!-- footer -->
<b-col>
<BCol>
<content-footer v-if="!$route.meta.hideFooter"></content-footer>
</b-col>
</b-row>
</BCol>
</BRow>
<session-logout-timeout @logout="logout"></session-logout-timeout>
</div>
</div>
<!-- <h1>TEST</h1>-->
</template>
<script>
<!--<script>-->
<!--import ContentHeader from '@/layouts/templates/ContentHeader'-->
<!--import CommunityTemplate from '@/layouts/templates/CommunityTemplate'-->
<!--import Breadcrumb from '@/components/Breadcrumb/breadcrumb'-->
<!--import RightSide from '@/layouts/templates/RightSide'-->
<!--import SkeletonOverview from '@/components/skeleton/Overview'-->
<!--import Navbar from '@/components/Menu/Navbar'-->
<!--import Sidebar from '@/components/Menu/Sidebar'-->
<!--import MobileSidebar from '@/components/MobileSidebar/MobileSidebar'-->
<!--import SessionLogoutTimeout from '@/components/SessionLogoutTimeout'-->
<!--import { transactionsQuery, communityStatistics } from '@/graphql/queries'-->
<!--import { logout } from '@/graphql/mutations'-->
<!--import ContentFooter from '@/components/ContentFooter'-->
<!--import { FadeTransition } from 'vue2-transitions'-->
<!--import CONFIG from '@/config'-->
<!--import GddAmount from '@/components/Template/ContentHeader/GddAmount'-->
<!--import GdtAmount from '@/components/Template/ContentHeader/GdtAmount'-->
<!--import CommunityMember from '@/components/Template/ContentHeader/CommunityMember'-->
<!--import NavCommunity from '@/components/Template/ContentHeader/NavCommunity'-->
<!--import LastTransactions from '@/components/Template/RightSide/LastTransactions'-->
<!--export default {-->
<!-- name: 'DashboardLayout',-->
<!-- components: {-->
<!-- SkeletonOverview,-->
<!-- ContentHeader,-->
<!-- RightSide,-->
<!-- Navbar,-->
<!-- Sidebar,-->
<!-- MobileSidebar,-->
<!-- SessionLogoutTimeout,-->
<!-- ContentFooter,-->
<!-- FadeTransition,-->
<!-- Breadcrumb,-->
<!-- GddAmount,-->
<!-- GdtAmount,-->
<!-- CommunityMember,-->
<!-- NavCommunity,-->
<!-- LastTransactions,-->
<!-- CommunityTemplate,-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- balance: 0,-->
<!-- GdtBalance: 0,-->
<!-- transactions: [],-->
<!-- transactionCount: 0,-->
<!-- transactionLinkCount: 0,-->
<!-- pending: true,-->
<!-- visible: false,-->
<!-- hamburger: true,-->
<!-- darkMode: false,-->
<!-- skeleton: true,-->
<!-- totalUsers: null,-->
<!-- }-->
<!-- },-->
<!-- created() {-->
<!-- this.updateTransactions(0)-->
<!-- this.getCommunityStatistics()-->
<!-- setTimeout(() => {-->
<!-- this.skeleton = false-->
<!-- }, 1500)-->
<!-- },-->
<!-- methods: {-->
<!-- async logout() {-->
<!-- this.$apollo-->
<!-- .mutate({-->
<!-- mutation: logout,-->
<!-- })-->
<!-- .then(() => {-->
<!-- this.$store.dispatch('logout')-->
<!-- this.$router.push('/login')-->
<!-- })-->
<!-- .catch(() => {-->
<!-- this.$store.dispatch('logout')-->
<!-- if (this.$router.currentRoute.path !== '/login') this.$router.push('/login')-->
<!-- })-->
<!-- },-->
<!-- async updateTransactions(pagination) {-->
<!-- this.pending = true-->
<!-- this.$apollo-->
<!-- .query({-->
<!-- query: transactionsQuery,-->
<!-- variables: {-->
<!-- currentPage: pagination.currentPage,-->
<!-- pageSize: pagination.pageSize,-->
<!-- },-->
<!-- fetchPolicy: 'network-only',-->
<!-- })-->
<!-- .then((result) => {-->
<!-- const {-->
<!-- data: { transactionList },-->
<!-- } = result-->
<!-- this.GdtBalance =-->
<!-- transactionList.balance.balanceGDT === null-->
<!-- ? 0-->
<!-- : Number(transactionList.balance.balanceGDT)-->
<!-- this.transactions = transactionList.transactions-->
<!-- this.balance = Number(transactionList.balance.balance)-->
<!-- this.transactionCount = transactionList.balance.count-->
<!-- this.transactionLinkCount = transactionList.balance.linkCount-->
<!-- this.pending = false-->
<!-- })-->
<!-- .catch((error) => {-->
<!-- this.pending = true-->
<!-- this.transactionCount = -1-->
<!-- this.toastError(error.message)-->
<!-- // what to do when loading balance fails?-->
<!-- })-->
<!-- },-->
<!-- async getCommunityStatistics() {-->
<!-- this.$apollo-->
<!-- .query({-->
<!-- query: communityStatistics,-->
<!-- })-->
<!-- .then((result) => {-->
<!-- this.totalUsers = result.data.communityStatistics.totalUsers-->
<!-- })-->
<!-- .catch(() => {-->
<!-- this.toastError('communityStatistics has no result, use default data')-->
<!-- })-->
<!-- },-->
<!-- admin() {-->
<!-- window.location.assign(CONFIG.ADMIN_AUTH_URL.replace('{token}', this.$store.state.token))-->
<!-- this.$store.dispatch('logout') // logout without redirect-->
<!-- },-->
<!-- setVisible(bool) {-->
<!-- this.visible = bool-->
<!-- },-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, onMounted } from 'vue'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'
import { useLazyQuery, useMutation, useQuery } from '@vue/apollo-composable'
import { useI18n } from 'vue-i18n'
import ContentHeader from '@/layouts/templates/ContentHeader'
import CommunityTemplate from '@/layouts/templates/CommunityTemplate'
import Breadcrumb from '@/components/Breadcrumb/breadcrumb'
@ -191,126 +331,96 @@ import Navbar from '@/components/Menu/Navbar'
import Sidebar from '@/components/Menu/Sidebar'
import MobileSidebar from '@/components/MobileSidebar/MobileSidebar'
import SessionLogoutTimeout from '@/components/SessionLogoutTimeout'
import { transactionsQuery, communityStatistics } from '@/graphql/queries'
import { logout } from '@/graphql/mutations'
import ContentFooter from '@/components/ContentFooter'
import { FadeTransition } from 'vue2-transitions'
import CONFIG from '@/config'
import GddAmount from '@/components/Template/ContentHeader/GddAmount'
import GdtAmount from '@/components/Template/ContentHeader/GdtAmount'
import CommunityMember from '@/components/Template/ContentHeader/CommunityMember'
import NavCommunity from '@/components/Template/ContentHeader/NavCommunity'
import LastTransactions from '@/components/Template/RightSide/LastTransactions'
import { transactionsQuery, communityStatistics } from '@/graphql/queries'
import { logout } from '@/graphql/mutations'
import CONFIG from '@/config'
import { useAppToast } from '../composables/useToast'
export default {
name: 'DashboardLayout',
components: {
SkeletonOverview,
ContentHeader,
RightSide,
Navbar,
Sidebar,
MobileSidebar,
SessionLogoutTimeout,
ContentFooter,
FadeTransition,
Breadcrumb,
GddAmount,
GdtAmount,
CommunityMember,
NavCommunity,
LastTransactions,
CommunityTemplate,
},
data() {
return {
balance: 0,
GdtBalance: 0,
transactions: [],
transactionCount: 0,
transactionLinkCount: 0,
pending: true,
visible: false,
hamburger: true,
darkMode: false,
skeleton: true,
totalUsers: null,
}
},
created() {
this.updateTransactions(0)
this.getCommunityStatistics()
setTimeout(() => {
this.skeleton = false
}, 1500)
},
methods: {
async logout() {
this.$apollo
.mutate({
mutation: logout,
})
.then(() => {
this.$store.dispatch('logout')
this.$router.push('/login')
})
.catch(() => {
this.$store.dispatch('logout')
if (this.$router.currentRoute.path !== '/login') this.$router.push('/login')
})
},
async updateTransactions(pagination) {
this.pending = true
this.$apollo
.query({
query: transactionsQuery,
variables: {
currentPage: pagination.currentPage,
pageSize: pagination.pageSize,
},
fetchPolicy: 'network-only',
})
.then((result) => {
const {
data: { transactionList },
} = result
this.GdtBalance =
transactionList.balance.balanceGDT === null
? 0
: Number(transactionList.balance.balanceGDT)
this.transactions = transactionList.transactions
this.balance = Number(transactionList.balance.balance)
this.transactionCount = transactionList.balance.count
this.transactionLinkCount = transactionList.balance.linkCount
this.pending = false
})
.catch((error) => {
this.pending = true
this.transactionCount = -1
this.toastError(error.message)
// what to do when loading balance fails?
})
},
async getCommunityStatistics() {
this.$apollo
.query({
query: communityStatistics,
})
.then((result) => {
this.totalUsers = result.data.communityStatistics.totalUsers
})
.catch(() => {
this.toastError('communityStatistics has no result, use default data')
})
},
admin() {
window.location.assign(CONFIG.ADMIN_AUTH_URL.replace('{token}', this.$store.state.token))
this.$store.dispatch('logout') // logout without redirect
},
setVisible(bool) {
this.visible = bool
},
},
const store = useStore()
const router = useRouter()
const { load: useCommunityStatsQuery } = useLazyQuery(communityStatistics)
const { load: useTransactionsQuery } = useLazyQuery(transactionsQuery)
const { mutate: useLogoutMutation } = useMutation(logout)
const { t } = useI18n()
const { toastError } = useAppToast()
const balance = ref(0)
const GdtBalance = ref(0)
const transactions = ref([])
const transactionCount = ref(0)
const transactionLinkCount = ref(0)
const pending = ref(true)
const visible = ref(false)
const hamburger = ref(true)
const darkMode = ref(false)
const skeleton = ref(true)
const totalUsers = ref(null)
onMounted(() => {
updateTransactions({ currentPage: 0, pageSize: 10 })
getCommunityStatistics()
setTimeout(() => {
skeleton.value = false
}, 1500)
})
const logoutUser = async () => {
try {
await useLogoutMutation()
await store.dispatch('logout')
await router.push('/login')
} catch {
await store.dispatch('logout')
if (router.currentRoute.value.path !== '/login') await router.push('/login')
}
}
const updateTransactions = async ({ currentPage, pageSize }) => {
pending.value = true
try {
// const { result } = useQuery(transactionsQuery, undefined, { fetchPolicy: 'network-only' })
// console.log(result)
const result = await useTransactionsQuery()
const { transactionList } = result
GdtBalance.value =
transactionList.balance.balanceGDT === null ? 0 : Number(transactionList.balance.balanceGDT)
transactions.value = transactionList.transactions
balance.value = Number(transactionList.balance.balance)
transactionCount.value = transactionList.balance.count
transactionLinkCount.value = transactionList.balance.linkCount
pending.value = false
} catch (error) {
pending.value = true
transactionCount.value = -1
toastError(error.message)
console.error(error)
}
}
const getCommunityStatistics = async () => {
try {
const result = await useCommunityStatsQuery()
console.log(result)
totalUsers.value = result.communityStatistics.totalUsers
} catch {
toastError(t('communityStatistics has no result, use default data'))
}
}
const admin = () => {
window.location.assign(CONFIG.ADMIN_AUTH_URL.replace('{token}', store.state.token))
store.dispatch('logout') // logout without redirect
}
const setVisible = (bool) => {
visible.value = bool
}
</script>
<style>

View File

@ -20,23 +20,28 @@
</p>
<ul>
<li>
<b-icon icon="bell-fill" variant="primary"></b-icon>
<!-- <b-icon icon="bell-fill" variant="primary"></b-icon>-->
<IBiBellFill />
{{ $t('contribution.alert.pending') }}
</li>
<li>
<b-icon icon="question" variant="205"></b-icon>
<!-- <b-icon icon="question" variant="205"></b-icon>-->
<IBiQuestion />
{{ $t('contribution.alert.in_progress') }}
</li>
<li>
<b-icon icon="check" variant="success"></b-icon>
<!-- <b-icon icon="check" variant="success"></b-icon>-->
<IBiCheck />
{{ $t('contribution.alert.confirm') }}
</li>
<li>
<b-icon icon="x-circle" variant="warning"></b-icon>
<!-- <b-icon icon="x-circle" variant="warning"></b-icon>-->
<IBiXCircle />
{{ $t('contribution.alert.denied') }}
</li>
<li>
<b-icon icon="trash" variant="danger"></b-icon>
<!-- <b-icon icon="trash" variant="danger"></b-icon>-->
<IBiTrash />
{{ $t('contribution.alert.deleted') }}
</li>
</ul>
@ -50,19 +55,23 @@
</p>
<ul>
<li>
<b-icon icon="bell-fill" variant="primary"></b-icon>
<!-- <b-icon icon="bell-fill" variant="primary"></b-icon>-->
<IBiBellFill />
{{ $t('contribution.alert.pending') }}
</li>
<li>
<b-icon icon="question" variant="205"></b-icon>
<!-- <b-icon icon="question" variant="205"></b-icon>-->
<IBiQuestion />
{{ $t('contribution.alert.in_progress') }}
</li>
<li>
<b-icon icon="check" variant="success"></b-icon>
<!-- <b-icon icon="check" variant="success"></b-icon>-->
<IBiCheck />
{{ $t('contribution.alert.confirm') }}
</li>
<li>
<b-icon icon="x-circle" variant="warning"></b-icon>
<!-- <b-icon icon="x-circle" variant="warning"></b-icon>-->
<IBiXCircle />
{{ $t('contribution.alert.denied') }}
</li>
</ul>

View File

@ -1,8 +1,8 @@
<template>
<div class="right-side mt-3 mt-lg-0">
<b-container>
<BContainer>
<slot :name="name" />
</b-container>
</BContainer>
</div>
</template>
<script>

View File

@ -343,6 +343,7 @@
"changeLanguage": "Sprache ändern",
"de": "Deutsch",
"en": "English",
"error": "Die Spracheinstellungen konnten nicht aktualisiert werden.",
"es": "Español",
"fr": "Français",
"nl": "Nederlands",

View File

@ -343,6 +343,7 @@
"changeLanguage": "Change language",
"de": "Deutsch",
"en": "English",
"error": "Failed to update language settings.",
"es": "Español",
"fr": "Français",
"nl": "Nederlands",

View File

@ -270,6 +270,7 @@
"changeLanguage": "Cambiar idioma",
"de": "Deutsch",
"en": "English",
"error": "No se ha podido actualizar la configuración de idioma.",
"es": "Español",
"fr": "Français",
"nl": "Nederlands",

View File

@ -280,6 +280,7 @@
"changeLanguage": "Changer la langue",
"de": "Deutsch",
"en": "English",
"error": "Échec de la mise à jour des paramètres linguistiques.",
"es": "Español",
"fr": "Français",
"nl": "Nederlands",

View File

@ -270,6 +270,7 @@
"changeLanguage": "Taal veranderen",
"de": "Deutsch",
"en": "English",
"error": "Het is niet gelukt om de taalinstellingen bij te werken.",
"es": "Español",
"fr": "Français",
"nl": "Nederlands",

View File

@ -247,6 +247,7 @@
"changeLanguage": "Dili değiştir",
"de": "Deutsch",
"en": "English",
"error": "Dil ayarları güncellenemedi.",
"es": "Español",
"fr": "Français",
"nl": "Nederlands",

View File

@ -1,11 +1,14 @@
import { createApp } from 'vue'
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue-next/dist/bootstrap-vue-next.css'
import '@/assets/scss/gradido.scss'
// import DashboardPlugin from './plugins/dashboard-plugin'
import App from './App'
import i18n from './i18n.js'
import { loadAllRules } from './validation-rules'
import { toasters } from './mixins/toaster'
import { loadFilters } from './filters/amount'
import 'regenerator-runtime'
@ -23,14 +26,13 @@ import 'clipboard-polyfill/overwrite-globals'
import { createBootstrap } from 'bootstrap-vue-next'
// Add the necessary CSS
import 'bootstrap/dist/css/bootstrap.css'
import 'bootstrap-vue-next/dist/bootstrap-vue-next.css'
// import 'bootstrap/dist/css/bootstrap.css'
// import 'bootstrap-vue-next/dist/bootstrap-vue-next.css'
// import GlobalComponents from '@/plugins/globalComponents'
import GlobalDirectives from '@/plugins/globalDirectives'
import PortalVue from 'portal-vue'
import FlatPickr from 'vue-flatpickr-component'
import Loading from 'vue-loading-overlay'
import VueApollo from 'vue-apollo'
const app = createApp(App)
@ -46,12 +48,11 @@ app.use(createBootstrap())
app.use(GlobalDirectives)
app.use(PortalVue)
app.use(FlatPickr)
app.use(Loading)
app.use(VueApollo)
app.use(apolloProvider)
// app.use(VueApollo)
app.use(() => apolloProvider)
// app.use(VueTimers)
app.mixin(toasters)
// app.mixin(toasters)
const filters = loadFilters(i18n)
app.filter('amount', filters.amount)
app.filter('GDD', filters.GDD)
@ -62,7 +63,7 @@ app.filter('GDD', filters.GDD)
// amount: filters.amount,
// }
loadAllRules(i18n, apolloProvider.defaultClient)
loadAllRules(i18n.global, apolloProvider.defaultClient)
addNavigationGuards(router, store, apolloProvider.defaultClient)

View File

@ -1,14 +1,14 @@
<template>
<div class="info-statistic">
<b-container class="bg-white appBoxShadow gradido-border-radius p-4 mt--3">
<BContainer class="bg-white appBoxShadow gradido-border-radius p-4 mt--3">
<div>{{ $t('communityInfo') }}</div>
<div class="h3">
{{ CONFIG.COMMUNITY_DESCRIPTION }}
</div>
<div>
<b-link :href="CONFIG.COMMUNITY_URL">
<BLink :href="CONFIG.COMMUNITY_URL">
{{ CONFIG.COMMUNITY_URL }}
</b-link>
</BLink>
</div>
<hr />
<!--<div class="h3">{{ $t('community.openContributionLinks') }}</div>
@ -48,9 +48,9 @@
<hr />
<div class="h3">{{ $t('contact') }}</div>
<b-link :href="`mailto:${supportMail}`">{{ supportMail }}</b-link>
</b-container>
<!--
<BLink :href="`mailto:${supportMail}`">{{ supportMail }}</BLink>
</BContainer>
<!--
<hr />
<b-container>
<div class="h3">{{ $t('community.statistic') }}</div>

View File

@ -56,16 +56,15 @@
<!--</template>-->
<template>
<div class="login-form">
{{ isValidating }}
<BContainer v-if="enterData">
<div class="pb-5" align="center">{{ $t('gdd_per_link.isFree') }}</div>
<form @submit.prevent="onSubmit">
<BRow>
<BCol sm="12" md="12" lg="6">
<input-email :name="$t('form.email')" />
<input-email />
</BCol>
<BCol sm="12" md="12" lg="6">
<input-password :name="$t('form.password')" />
<input-password />
</BCol>
</BRow>
<BRow>
@ -79,9 +78,10 @@
<BCol cols="12" lg="6">
<BButton
type="submit"
:variant="isValidating ? 'gradido' : 'gradido-disable'"
ref="submitBtn"
:variant="meta.valid ? 'gradido' : 'gradido-disable'"
block
:disabled="!isValidating"
:disabled="!meta.valid"
>
{{ $t('login') }}
</BButton>
@ -191,85 +191,77 @@ import { useStore } from 'vuex'
import { useI18n } from 'vue-i18n'
import { useRouter, useRoute } from 'vue-router'
import { useForm } from 'vee-validate'
import * as yup from 'yup'
import { useMutation } from '@vue/apollo-composable'
import { useAppToast } from '@/composables/useToast'
// import { useLoading } from 'vue-loading-overlay'
// Define validation schema
const schema = yup.object({
email: yup.string().email('Email must be valid').required('Email is required'),
password: yup
.string()
.required('Password is required')
.min(8, 'Password must be at least 8 characters'),
})
const router = useRouter()
const route = useRoute()
const store = useStore()
const { t } = useI18n()
const { mutate } = useMutation(login)
// const $loading = useLoading() // TODO needs to be updated but there is some sort of an issue that breaks the app.
const { toastError } = useAppToast()
const form = ref({
email: '',
password: '',
})
// const { handleSubmit, isValid } = useForm({
// validationSchema: schema,
// })
//
const { values, errors, handleSubmit, isValidating } = useForm({ validationSchema: schema })
const { handleSubmit, meta, values } = useForm({
initialValues: form.value,
})
const passwordVisible = ref(false)
const showPageMessage = ref(false)
const errorReason = ref(null)
const errorSubtitle = ref('')
const errorLinkTo = ref('')
const store = useStore()
const { t } = useI18n()
const router = useRouter()
const route = useRoute()
const submitBtn = ref(null)
const onSubmit = handleSubmit(async (values) => {
const loader = this.$loading.show({
container: this.$refs.submitButton,
})
this.$root.$bvToast.hide()
// const loader = $loading.show({
// container: submitBtn,
// })
// this.$root.$bvToast.hide()
try {
const result = await this.$apollo.mutate({
mutation: login,
variables: {
email: values.email,
password: values.password,
publisherId: store.state.publisherId,
},
const result = await mutate({
email: values.email,
password: values.password,
publisherId: store.state.publisherId,
})
const {
data: { login },
} = result
await store.dispatch('login', login)
const { login: loginResponse } = result.data
await store.dispatch('login', loginResponse)
store.commit('email', values.email)
await loader.hide()
// await loader.hide()
if (route.params.code) {
router.push(`/redeem/${route.params.code}`)
await router.push(`/redeem/${route.params.code}`)
} else {
router.push(store.state.redirectPath)
await router.push(store.state.redirectPath)
}
} catch (error) {
if (error.message.includes('User email not validated')) {
showPageMessage.value = true
errorSubtitle.value = t('message.activateEmail')
errorLinkTo.value = '/forgot-password'
this.toastError(t('error.no-account'))
toastError(t('error.no-account'))
} else if (error.message.includes('User has no password set yet')) {
showPageMessage.value = true
errorSubtitle.value = t('message.unsetPassword')
errorLinkTo.value = '/reset-password/login'
this.toastError(t('error.no-account'))
toastError(t('error.no-account'))
} else if (error.message.includes('No user with this credentials')) {
this.toastError(t('error.no-user'))
toastError(t('error.no-user'))
} else {
this.toastError(t('error.unknown-error') + error.message)
toastError(t('error.unknown-error') + error.message)
}
loader.hide()
} finally {
// loader.hide()
}
})
const enterData = computed(() => !showPageMessage.value)
// const isFormValid = computed(() => isValid.value)
</script>
<style scoped>
.btn-gradido {

View File

@ -2,7 +2,7 @@
<div>
<!-- Header -->
<div class="header py-1 py-lg-1 pt-lg-3">
<b-container>
<BContainer>
<div class="header-body text-center mb-3">
<a href="#!" v-on:click="$router.go(-1)">
<div class="container">
@ -1183,12 +1183,12 @@
</div>
</a>
</div>
</b-container>
</BContainer>
</div>
<div class="text-center">
<b-button class="test-back" variant="light" v-on:click="$router.go(-1)">
<BButton class="test-back" variant="light" v-on:click="$router.go(-1)">
{{ $t('back') }}
</b-button>
</BButton>
</div>
</div>
</template>

View File

@ -21,83 +21,172 @@
</div>
</div>
</template>
<script>
<!--<script>-->
<!--import GddTransactionList from '@/components/GddTransactionList'-->
<!--import GdtTransactionList from '@/components/GdtTransactionList'-->
<!--import { listGDTEntriesQuery } from '@/graphql/queries'-->
<!--export default {-->
<!-- name: 'Transactions',-->
<!-- components: {-->
<!-- GddTransactionList,-->
<!-- GdtTransactionList,-->
<!-- },-->
<!-- props: {-->
<!-- gdt: { type: Boolean, default: false },-->
<!-- transactions: {-->
<!-- default: () => [],-->
<!-- },-->
<!-- transactionCount: { type: Number, default: 0 },-->
<!-- transactionLinkCount: { type: Number, default: 0 },-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- timestamp: Date.now(),-->
<!-- transactionsGdt: [],-->
<!-- transactionGdtCount: 0,-->
<!-- currentPage: 1,-->
<!-- pageSize: 25,-->
<!-- tabIndex: 0,-->
<!-- }-->
<!-- },-->
<!-- methods: {-->
<!-- async updateGdt() {-->
<!-- this.$apollo-->
<!-- .query({-->
<!-- query: listGDTEntriesQuery,-->
<!-- variables: {-->
<!-- currentPage: this.currentPage,-->
<!-- pageSize: this.pageSize,-->
<!-- },-->
<!-- fetchPolicy: 'network-only',-->
<!-- })-->
<!-- .then((result) => {-->
<!-- const {-->
<!-- data: { listGDTEntries },-->
<!-- } = result-->
<!-- this.transactionsGdt = listGDTEntries.gdtEntries-->
<!-- this.transactionGdtCount = listGDTEntries.count-->
<!-- window.scrollTo(0, 0)-->
<!-- // eslint-disable-next-line no-unused-expressions-->
<!-- this.$route.path === '/transactions' ? this.$router.replace('/gdt') : ''-->
<!-- })-->
<!-- .catch((error) => {-->
<!-- this.transactionGdtCount = -1-->
<!-- this.toastError(error.message)-->
<!-- })-->
<!-- },-->
<!-- updateTransactions(pagination) {-->
<!-- this.$emit('update-transactions', pagination)-->
<!-- },-->
<!-- },-->
<!-- created() {-->
<!-- if (this.gdt) {-->
<!-- this.updateGdt()-->
<!-- }-->
<!-- },-->
<!-- watch: {-->
<!-- currentPage() {-->
<!-- if (this.gdt) {-->
<!-- this.updateGdt()-->
<!-- }-->
<!-- },-->
<!-- gdt() {-->
<!-- if (this.gdt) {-->
<!-- this.updateGdt()-->
<!-- }-->
<!-- },-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import { ref, watch, onMounted } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useLazyQuery } from '@vue/apollo-composable'
import GddTransactionList from '@/components/GddTransactionList'
import GdtTransactionList from '@/components/GdtTransactionList'
import { listGDTEntriesQuery } from '@/graphql/queries'
import { useAppToast } from '../composables/useToast'
export default {
name: 'Transactions',
components: {
GddTransactionList,
GdtTransactionList,
},
props: {
gdt: { type: Boolean, default: false },
transactions: {
default: () => [],
},
transactionCount: { type: Number, default: 0 },
transactionLinkCount: { type: Number, default: 0 },
},
data() {
return {
timestamp: Date.now(),
transactionsGdt: [],
transactionGdtCount: 0,
currentPage: 1,
pageSize: 25,
tabIndex: 0,
}
},
methods: {
async updateGdt() {
this.$apollo
.query({
query: listGDTEntriesQuery,
variables: {
currentPage: this.currentPage,
pageSize: this.pageSize,
},
fetchPolicy: 'network-only',
})
.then((result) => {
const {
data: { listGDTEntries },
} = result
this.transactionsGdt = listGDTEntries.gdtEntries
this.transactionGdtCount = listGDTEntries.count
window.scrollTo(0, 0)
// eslint-disable-next-line no-unused-expressions
this.$route.path === '/transactions' ? this.$router.replace('/gdt') : ''
})
.catch((error) => {
this.transactionGdtCount = -1
this.toastError(error.message)
})
},
updateTransactions(pagination) {
this.$emit('update-transactions', pagination)
},
},
created() {
if (this.gdt) {
this.updateGdt()
}
},
watch: {
currentPage() {
if (this.gdt) {
this.updateGdt()
}
},
gdt() {
if (this.gdt) {
this.updateGdt()
}
},
const props = defineProps({
gdt: { type: Boolean, default: false },
transactions: {
default: () => [],
},
transactionCount: { type: Number, default: 0 },
transactionLinkCount: { type: Number, default: 0 },
})
const emit = defineEmits(['update-transactions'])
const timestamp = ref(Date.now())
const transactionsGdt = ref([])
const transactionGdtCount = ref(0)
const currentPage = ref(1)
const pageSize = ref(25)
const tabIndex = ref(0)
const { toastError } = useAppToast()
const route = useRoute()
const router = useRouter()
const variables = ref({
currentPage: currentPage.value,
pageSize: pageSize.value,
})
const { load: loadGdt, onResult, onError } = useLazyQuery(listGDTEntriesQuery, variables, {
fetchPolicy: 'network-only',
})
const updateGdt = async () => {
variables.value = {
currentPage: currentPage.value,
pageSize: pageSize.value,
}
await loadGdt()
}
const updateTransactions = (pagination) => {
emit('update-transactions', pagination)
}
onResult((result) => {
const { listGDTEntries } = result.data
transactionsGdt.value = listGDTEntries.gdtEntries
transactionGdtCount.value = listGDTEntries.count
window.scrollTo(0, 0)
if (route.path === '/transactions') {
router.replace('/gdt')
}
})
onError((error) => {
transactionGdtCount.value = -1
toastError(error.message)
})
watch(
() => props.gdt,
(newVal) => {
if (newVal) {
updateGdt()
}
},
)
watch(currentPage, () => {
if (props.gdt) {
updateGdt()
}
})
onMounted(() => {
if (props.gdt) {
updateGdt()
}
})
</script>
<style>
.nav-tabs > li > a {

View File

@ -4,6 +4,7 @@ import router from '../routes/router'
import i18n from '../i18n'
import { createHttpLink, ApolloLink, ApolloClient, InMemoryCache } from '@apollo/client/core'
import { createApolloProvider } from '@vue/apollo-option'
import { provideApolloClient } from '@vue/apollo-composable'
const httpLink = createHttpLink({ uri: CONFIG.GRAPHQL_URI })
@ -37,6 +38,8 @@ const apolloClient = new ApolloClient({
}),
})
provideApolloClient(apolloClient)
export const apolloProvider = createApolloProvider({
defaultClient: apolloClient,
})

View File

@ -1,13 +1,13 @@
import Vue from 'vue'
import Vuex, { createStore } from 'vuex'
import { createStore } from 'vuex'
import createPersistedState from 'vuex-persistedstate'
// import { localeChanged } from 'vee-validate'
import i18n from '@/i18n.js'
import jwtDecode from 'jwt-decode'
import i18n from '../i18n'
export const mutations = {
language: (state, language) => {
i18n.locale = language
i18n.global.locale.value = language
// localeChanged(language)
state.language = language
},

View File

@ -1,176 +1,300 @@
// 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'
// eslint-disable-next-line camelcase
import { required, email, min, max, is_not } from '@vee-validate/rules'
import { required, email, min, max } from '@vee-validate/rules'
import { checkUsername } from '@/graphql/queries'
import { validate as validateUuid, version as versionUuid } from 'uuid'
import { localize } from '@vee-validate/i18n'
import en from '@vee-validate/i18n/dist/locale/en.json'
import de from '@vee-validate/i18n/dist/locale/de.json'
import es from '@vee-validate/i18n/dist/locale/es.json'
import fr from '@vee-validate/i18n/dist/locale/fr.json'
import nl from '@vee-validate/i18n/dist/locale/nl.json'
import tr from '@vee-validate/i18n/dist/locale/tr.json'
// taken from vee-validate
// eslint-disable-next-line no-useless-escape
// Email and username regex patterns remain the same
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) => {
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!
},
generateMessage: localize({
en,
de,
es,
fr,
nl,
tr,
}),
validateOnBlur: true,
validateOnChange: true,
validateOnInput: false,
validateOnModelUpdate: true,
})
defineRule('email', (value) => {
const isValid = email(value)
if (!isValid) {
return i18nCallback.t('validations.messages.email', value)
}
return true
// Define built-in rules
defineRule('required', required)
defineRule('email', email)
defineRule('min', min)
defineRule('max', max)
// ------ Custom rules ------
defineRule('gddSendAmount', (value, { min, max }) => {
value = value.replace(',', '.')
return value.match(/^[0-9]+(\.[0-9]{0,2})?$/) && Number(value) >= min && Number(value) <= max
? true
: i18nCallback.t('form.validation.gddSendAmount', {
min: i18nCallback.n(min, 'ungroupedDecimal'),
max: i18nCallback.n(max, 'ungroupedDecimal'),
})
})
defineRule('required', (value) => {
const valueExists = required(value)
if (!valueExists) {
return i18nCallback.t('validations.messages.required', value)
}
return true
defineRule('gddCreationTime', (value, { min, max }) => {
return value >= min && value <= max
? true
: i18nCallback.t('form.validation.gddCreationTime', { min, max })
})
defineRule('min', (value, limit) => {
return min(value, limit) ? true : i18nCallback.t('validations.messages.min', value)
defineRule('is_not', (value, [otherValue]) => {
return value !== otherValue
? true
: i18nCallback.t('form.validation.is-not', { other: otherValue })
})
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
return !!value.match(/[a-z]+/) || i18nCallback.t('site.signup.lowercase')
})
defineRule('containsUppercaseCharacter', (value) => {
const isValid = !!value.match(/[A-Z]+/)
if (!isValid) {
i18nCallback.t('site.signup.uppercase', { value })
}
return !!value.match(/[A-Z]+/) || i18nCallback.t('site.signup.uppercase')
})
// 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),
// })
defineRule('containsNumericCharacter', (value) => {
return !!value.match(/[0-9]+/) || i18nCallback.t('site.signup.one_number')
})
defineRule('atLeastEightCharacters', (value) => {
return !!value.match(/.{8,}/) || i18nCallback.t('site.signup.minimum')
})
defineRule('atLeastOneSpecialCharater', (value) => {
return !!value.match(/[^a-zA-Z0-9 \t\n\r]/) || i18nCallback.t('site.signup.special-char')
})
defineRule('noWhitespaceCharacters', (value) => {
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('usernameAllowedChars', (value) => {
return (
!!value.match(/^[a-zA-Z0-9_-]+$/) || i18nCallback.t('form.validation.username-allowed-chars')
)
})
defineRule('usernameHyphens', (value) => {
return (
!!value.match(/^[a-zA-Z0-9]+(?:[_-][a-zA-Z0-9]+?)*$/) ||
i18nCallback.t('form.validation.username-hyphens')
)
})
defineRule('usernameUnique', async (value) => {
if (!value.match(USERNAME_REGEX)) return true
const { data } = await apollo.query({
query: checkUsername,
variables: { username: value },
})
return data.checkUsername || i18nCallback.t('form.validation.username-unique')
})
defineRule('validIdentifier', (value) => {
const isEmail = !!EMAIL_REGEX.test(value)
const isUsername = !!value.match(USERNAME_REGEX)
const isGradidoId = validateUuid(value) && versionUuid(value) === 4
return (
isEmail || isUsername || isGradidoId || i18nCallback.t('form.validation.valid-identifier')
)
})
}

View File

@ -2,6 +2,9 @@ import { defineConfig } from 'vite'
import commonjs from 'vite-plugin-commonjs'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import Icons from 'unplugin-icons/vite'
import IconsResolve from 'unplugin-icons/resolver'
import { BootstrapVueNextResolver } from 'bootstrap-vue-next'
const path = require('path')
@ -31,7 +34,12 @@ export default defineConfig({
},
}),
Components({
resolvers: [BootstrapVueNextResolver()],
resolvers: [BootstrapVueNextResolver(), IconsResolve()],
dts: true,
}),
Icons({
compiler: 'vue3',
autoInstall: true,
}),
commonjs(),
],

View File

@ -2,6 +2,21 @@
# yarn lockfile v1
"@antfu/install-pkg@^0.1.1":
version "0.1.1"
resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-0.1.1.tgz#157bb04f0de8100b9e4c01734db1a6c77e98bbb5"
integrity sha512-LyB/8+bSfa0DFGC06zpCEfs89/XoWZwws5ygEa5D+Xsm3OfI+aXQ86VgVG7Acyef+rSZ5HE7J8rrxzrQeM3PjQ==
dependencies:
execa "^5.1.1"
find-up "^5.0.0"
"@antfu/install-pkg@^0.3.3":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-0.3.3.tgz#34c3837132157e6ca23fe9587d1e174b0f33dc1a"
integrity sha512-nHHsk3NXQ6xkCfiRRC8Nfrg8pU5kkr3P3Y9s9dKqiuRmBD0Yap7fymNDjGFKeWhZQHqqbCS5CfeMy9wtExM24w==
dependencies:
"@jsdevtools/ez-spawn" "^3.0.4"
"@antfu/utils@^0.7.10":
version "0.7.10"
resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-0.7.10.tgz#ae829f170158e297a9b6a28f161a8e487d00814d"
@ -1420,6 +1435,31 @@
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.1.1.tgz#076d78ce99822258cf813ecc1e7fa460fa74d052"
integrity sha512-NQ17ii0rK1b34VZonlmT2QMJFI70m0TRwbknO/ihlbatXyaktDhN/98vBiUU6kNBPljqGqyIrl2T4nY2RpFANg==
"@iconify-json/bi@^1.1.23":
version "1.1.23"
resolved "https://registry.yarnpkg.com/@iconify-json/bi/-/bi-1.1.23.tgz#e70433b04609e96c8e5152867a55f82988ae0e70"
integrity sha512-1te+g9ZzI+PU1Lv6Xerd3XPXf4DE6g3TvDL2buIopTAfrauPHyXCHPFQMrzoQVNrVPCpN3rv3vBtJMPyBwJ9IA==
dependencies:
"@iconify/types" "*"
"@iconify/types@*", "@iconify/types@^2.0.0":
version "2.0.0"
resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57"
integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==
"@iconify/utils@^2.1.29":
version "2.1.29"
resolved "https://registry.yarnpkg.com/@iconify/utils/-/utils-2.1.29.tgz#0ec13fb0376089059dac25fa890a7040f11ea229"
integrity sha512-wCcTsmlJvTi1VWBgcJ7HeuWlh7gLGWY7L9HmbgMfjOfsoo7DADemB2Nqnrw1KvCdEAxLL5wTMBAOP5BesFrtng==
dependencies:
"@antfu/install-pkg" "^0.1.1"
"@antfu/utils" "^0.7.10"
"@iconify/types" "^2.0.0"
debug "^4.3.5"
kolorist "^1.8.0"
local-pkg "^0.5.0"
mlly "^1.7.1"
"@intlify/core-base@9.13.1":
version "9.13.1"
resolved "https://registry.yarnpkg.com/@intlify/core-base/-/core-base-9.13.1.tgz#bd1f38e665095993ef9b67aeeb794f3cabcb515d"
@ -1742,6 +1782,16 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
"@jsdevtools/ez-spawn@^3.0.4":
version "3.0.4"
resolved "https://registry.yarnpkg.com/@jsdevtools/ez-spawn/-/ez-spawn-3.0.4.tgz#5641eb26fee6d31ec29f6788eba849470c52c7ff"
integrity sha512-f5DRIOZf7wxogefH03RjMPMdBF7ADTWUMoOs9kaJo06EfwF+aFhMZMDZxHg/Xe12hptN9xoZjGso2fdjapBRIA==
dependencies:
call-me-maybe "^1.0.1"
cross-spawn "^7.0.3"
string-argv "^0.3.1"
type-detect "^4.0.8"
"@nodelib/fs.scandir@2.1.4":
version "2.1.4"
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.4.tgz#d4b3549a5db5de2683e0c1071ab4f140904bbf69"
@ -1987,6 +2037,11 @@
"@typescript-eslint/types" "4.19.0"
eslint-visitor-keys "^2.0.0"
"@vee-validate/i18n@^4.13.2":
version "4.13.2"
resolved "https://registry.yarnpkg.com/@vee-validate/i18n/-/i18n-4.13.2.tgz#2787f59a911721c3a656e7673cf804b2b11c58b0"
integrity sha512-GWqGgxJsQwZZCcrQOsvLNcvxLk1DmHctGw8vYXvwgqoj2hyrLtGQSmeIAqUVa2cYR6rk7301Ity5iJgOou9K5A==
"@vee-validate/rules@^4.13.2":
version "4.13.2"
resolved "https://registry.yarnpkg.com/@vee-validate/rules/-/rules-4.13.2.tgz#f460970883bcf528235180c818bc5c9aafc8e453"
@ -2008,6 +2063,15 @@
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.2.0.tgz#a1484089dd85d6528f435743f84cdd0d215bbb54"
integrity sha512-E0tnaL4fr+qkdCNxJ+Xd0yM31UwMkQje76fsDVBBUCoGOUPexu2VDUYHL8P4CwV+zMvWw6nlRw19OnRKmYAJpw==
"@vue/apollo-composable@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@vue/apollo-composable/-/apollo-composable-4.0.2.tgz#ea3c001d25b3bf659aad5ae7a849fed3928aaa35"
integrity sha512-/yfEktliXw+oMy/6n9C0J05woYoKlM+kcffVXMh0qljbXdrioyj0WkR/LgPdpnRf6TglFnjIgCKKicd5Gyzpnw==
dependencies:
throttle-debounce "^5.0.0"
ts-essentials "^9.4.0"
vue-demi "^0.14.6"
"@vue/apollo-option@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@vue/apollo-option/-/apollo-option-4.0.0.tgz#4fbbb7b1b17961e500ae439a90f7c2c8d82e8928"
@ -2035,6 +2099,17 @@
estree-walker "^2.0.2"
source-map-js "^1.2.0"
"@vue/compiler-core@3.4.35":
version "3.4.35"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.4.35.tgz#421922a75ecabf1aabc6b7a2ce98b5acb2fc2d65"
integrity sha512-gKp0zGoLnMYtw4uS/SJRRO7rsVggLjvot3mcctlMXunYNsX+aRJDqqw/lV5/gHK91nvaAAlWFgdVl020AW1Prg==
dependencies:
"@babel/parser" "^7.24.7"
"@vue/shared" "3.4.35"
entities "^4.5.0"
estree-walker "^2.0.2"
source-map-js "^1.2.0"
"@vue/compiler-dom@3.4.31":
version "3.4.31"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.31.tgz#30961ca847f5d6ad18ffa26236c219f61b195f6b"
@ -2043,6 +2118,14 @@
"@vue/compiler-core" "3.4.31"
"@vue/shared" "3.4.31"
"@vue/compiler-dom@3.4.35":
version "3.4.35"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.4.35.tgz#cd0881f1b4ed655cd96367bce4845f87023a5a2d"
integrity sha512-pWIZRL76/oE/VMhdv/ovZfmuooEni6JPG1BFe7oLk5DZRo/ImydXijoZl/4kh2406boRQ7lxTYzbZEEXEhj9NQ==
dependencies:
"@vue/compiler-core" "3.4.35"
"@vue/shared" "3.4.35"
"@vue/compiler-sfc@3.4.31":
version "3.4.31"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.31.tgz#cc6bfccda17df8268cc5440842277f61623c591f"
@ -2058,6 +2141,21 @@
postcss "^8.4.38"
source-map-js "^1.2.0"
"@vue/compiler-sfc@^3.4.35":
version "3.4.35"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.4.35.tgz#16f87dd3bdab64cef14d3a6fcf53f8673e404071"
integrity sha512-xacnRS/h/FCsjsMfxBkzjoNxyxEyKyZfBch/P4vkLRvYJwe5ChXmZZrj8Dsed/752H2Q3JE8kYu9Uyha9J6PgA==
dependencies:
"@babel/parser" "^7.24.7"
"@vue/compiler-core" "3.4.35"
"@vue/compiler-dom" "3.4.35"
"@vue/compiler-ssr" "3.4.35"
"@vue/shared" "3.4.35"
estree-walker "^2.0.2"
magic-string "^0.30.10"
postcss "^8.4.40"
source-map-js "^1.2.0"
"@vue/compiler-ssr@3.4.31":
version "3.4.31"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.31.tgz#f62ffecdf15bacb883d0099780cf9a1e3654bfc4"
@ -2066,6 +2164,14 @@
"@vue/compiler-dom" "3.4.31"
"@vue/shared" "3.4.31"
"@vue/compiler-ssr@3.4.35":
version "3.4.35"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.4.35.tgz#0774c9a0afed74d71615209904b38f3fa9711adb"
integrity sha512-7iynB+0KB1AAJKk/biENTV5cRGHRdbdaD7Mx3nWcm1W8bVD6QmnH3B4AHhQQ1qZHhqFwzEzMwiytXm3PX1e60A==
dependencies:
"@vue/compiler-dom" "3.4.35"
"@vue/shared" "3.4.35"
"@vue/devtools-api@^6.0.0-beta.11", "@vue/devtools-api@^6.5.0", "@vue/devtools-api@^6.5.1", "@vue/devtools-api@^6.6.1":
version "6.6.3"
resolved "https://registry.yarnpkg.com/@vue/devtools-api/-/devtools-api-6.6.3.tgz#b23a588154cba8986bba82b6e1d0248bde3fd1a0"
@ -2118,6 +2224,11 @@
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.31.tgz#af9981f57def2c3f080c14bf219314fc0dc808a0"
integrity sha512-Yp3wtJk//8cO4NItOPpi3QkLExAr/aLBGZMmTtW9WpdwBCJpRM6zj9WgWktXAl8IDIozwNMByT45JP3tO3ACWA==
"@vue/shared@3.4.35":
version "3.4.35"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.4.35.tgz#5432f4b1c79e763fcf78cc830faf59ff01248968"
integrity sha512-hvuhBYYDe+b1G8KHxsQ0diDqDMA8D9laxWZhNAjE83VZb5UDaXl9Xnz7cGdDSyiHM90qqI/CyGMcpBpiDy6VVQ==
"@vue/test-utils@^1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@vue/test-utils/-/test-utils-1.1.3.tgz#747f5683d8d4633c85a385fe2e02c1bb35bec153"
@ -2245,7 +2356,7 @@ acorn@^8.0.5:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.1.0.tgz#52311fd7037ae119cbb134309e901aa46295b3fe"
integrity sha512-LWCF/Wn0nfHOmJ9rzQApGnxnvgfROzGilS8936rqN/lfcYkY9MYZzdMqN+2NJ4SlTc+m5HiSa+kNfDtI64dwUA==
acorn@^8.11.3, acorn@^8.8.2:
acorn@^8.11.3, acorn@^8.12.1, acorn@^8.8.2:
version "8.12.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248"
integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
@ -3027,6 +3138,11 @@ call-bind@^1.0.0, call-bind@^1.0.2:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
call-me-maybe@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.2.tgz#03f964f19522ba643b1b0693acb9152fe2074baa"
integrity sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==
callsites@^3.0.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73"
@ -3420,7 +3536,7 @@ cross-spawn@^6.0.0:
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2:
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
@ -3548,6 +3664,13 @@ debug@^4.3.5:
dependencies:
ms "2.1.2"
debug@^4.3.6:
version "4.3.6"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.6.tgz#2ab2c38fbaffebf8aa95fdfe6d88438c7a13c52b"
integrity sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==
dependencies:
ms "2.1.2"
decamelize-keys@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/decamelize-keys/-/decamelize-keys-1.1.0.tgz#d171a87933252807eb3cb61dc1c1445d078df2d9"
@ -4385,6 +4508,21 @@ execa@^4.0.0:
signal-exit "^3.0.2"
strip-final-newline "^2.0.0"
execa@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd"
integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==
dependencies:
cross-spawn "^7.0.3"
get-stream "^6.0.0"
human-signals "^2.1.0"
is-stream "^2.0.0"
merge-stream "^2.0.0"
npm-run-path "^4.0.1"
onetime "^5.1.2"
signal-exit "^3.0.3"
strip-final-newline "^2.0.0"
execall@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/execall/-/execall-2.0.0.tgz#16a06b5fe5099df7d00be5d9c06eecded1663b45"
@ -4672,6 +4810,14 @@ find-up@^4.0.0, find-up@^4.1.0:
locate-path "^5.0.0"
path-exists "^4.0.0"
find-up@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc"
integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==
dependencies:
locate-path "^6.0.0"
path-exists "^4.0.0"
flat-cache@^3.0.4:
version "3.0.4"
resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11"
@ -4818,6 +4964,11 @@ get-stream@^5.0.0:
dependencies:
pump "^3.0.0"
get-stream@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==
get-value@^2.0.3, get-value@^2.0.6:
version "2.0.6"
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
@ -4961,10 +5112,10 @@ graphql-tag@^2.4.2:
dependencies:
tslib "^2.1.0"
graphql@^15.5.1:
version "15.5.1"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.1.tgz#f2f84415d8985e7b84731e7f3536f8bb9d383aad"
integrity sha512-FeTRX67T3LoE3LWAxxOlW2K3Bz+rMYAC18rRguK4wgXaTZMiJwSUwDmPFo3UadAKbzirKIg5Qy+sNJXbpPRnQw==
graphql@^16.9.0:
version "16.9.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.9.0.tgz#1c310e63f16a49ce1fbb230bd0a000e99f6f115f"
integrity sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==
growly@^1.3.0:
version "1.3.0"
@ -5195,6 +5346,11 @@ human-signals@^1.1.1:
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3"
integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==
human-signals@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0"
integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==
iconv-lite@0.4.24:
version "0.4.24"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b"
@ -6262,6 +6418,11 @@ known-css-properties@^0.24.0:
resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.24.0.tgz#19aefd85003ae5698a5560d2b55135bf5432155c"
integrity sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA==
kolorist@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c"
integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==
leven@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2"
@ -6348,6 +6509,13 @@ locate-path@^5.0.0:
dependencies:
p-locate "^4.1.0"
locate-path@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286"
integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==
dependencies:
p-locate "^5.0.0"
lodash.clonedeep@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef"
@ -6789,7 +6957,7 @@ npm-run-path@^2.0.0:
dependencies:
path-key "^2.0.0"
npm-run-path@^4.0.0:
npm-run-path@^4.0.0, npm-run-path@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea"
integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==
@ -6906,7 +7074,7 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
dependencies:
wrappy "1"
onetime@^5.1.0:
onetime@^5.1.0, onetime@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e"
integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==
@ -6978,6 +7146,13 @@ p-limit@^2.0.0, p-limit@^2.2.0:
dependencies:
p-try "^2.0.0"
p-limit@^3.0.2:
version "3.1.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b"
integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==
dependencies:
yocto-queue "^0.1.0"
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
@ -6999,6 +7174,13 @@ p-locate@^4.1.0:
dependencies:
p-limit "^2.2.0"
p-locate@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834"
integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==
dependencies:
p-limit "^3.0.2"
p-try@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
@ -7274,6 +7456,15 @@ postcss@^8.4.18, postcss@^8.4.38:
picocolors "^1.0.1"
source-map-js "^1.2.0"
postcss@^8.4.40:
version "8.4.40"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.40.tgz#eb81f2a4dd7668ed869a6db25999e02e9ad909d8"
integrity sha512-YF2kKIUzAofPMpfH6hOi2cGnv/HrUlfucspc7pDyvv7kGdqXrfj8SCl/t8owkEgKEuu8ZcRjSOxFxVLqwChZ2Q==
dependencies:
nanoid "^3.3.7"
picocolors "^1.0.1"
source-map-js "^1.2.0"
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@ -7959,7 +8150,7 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af"
integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==
signal-exit@^3.0.7:
signal-exit@^3.0.3, signal-exit@^3.0.7:
version "3.0.7"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9"
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
@ -8153,6 +8344,11 @@ stealthy-require@^1.1.1:
resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b"
integrity sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks=
string-argv@^0.3.1:
version "0.3.2"
resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6"
integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==
string-length@^4.0.1:
version "4.0.2"
resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a"
@ -8599,6 +8795,11 @@ trim-newlines@^3.0.0:
resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-3.0.1.tgz#260a5d962d8b752425b32f3a7db0dcacd176c144"
integrity sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==
ts-essentials@^9.4.0:
version "9.4.2"
resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-9.4.2.tgz#6d4bd23b46b61bf3e031816cc887e839eb62c33c"
integrity sha512-mB/cDhOvD7pg3YCLk2rOtejHjjdSi9in/IBYE13S+8WA5FBSraYf4V/ws55uvs0IvQ/l0wBOlXy5yBNZ9Bl8ZQ==
ts-invariant@^0.10.3:
version "0.10.3"
resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.10.3.tgz#3e048ff96e91459ffca01304dbc7f61c1f642f6c"
@ -8686,6 +8887,11 @@ type-detect@4.0.8:
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
type-detect@^4.0.8:
version "4.1.0"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.1.0.tgz#deb2453e8f08dcae7ae98c626b13dddb0155906c"
integrity sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==
type-fest@^0.11.0:
version "0.11.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.11.0.tgz#97abf0872310fed88a5c466b25681576145e33f1"
@ -8802,6 +9008,19 @@ unpipe@1.0.0, unpipe@~1.0.0:
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
unplugin-icons@^0.19.1:
version "0.19.1"
resolved "https://registry.yarnpkg.com/unplugin-icons/-/unplugin-icons-0.19.1.tgz#82934cc7353f5d0e5423c859cd22e7a39f854594"
integrity sha512-a5I+wSOO5lsgc4dB2nEFaSZ4eEgQvSSR8tSR2jT69nTKiVmcK+PPU633zn2FyRf9i6vLapUiQ28GQStfzGURdg==
dependencies:
"@antfu/install-pkg" "^0.3.3"
"@antfu/utils" "^0.7.10"
"@iconify/utils" "^2.1.29"
debug "^4.3.6"
kolorist "^1.8.0"
local-pkg "^0.5.0"
unplugin "^1.12.0"
unplugin-vue-components@^0.27.3:
version "0.27.3"
resolved "https://registry.yarnpkg.com/unplugin-vue-components/-/unplugin-vue-components-0.27.3.tgz#e7a9980f7feb649306aa92afd61b760385479d42"
@ -8828,6 +9047,16 @@ unplugin@^1.11.0:
webpack-sources "^3.2.3"
webpack-virtual-modules "^0.6.1"
unplugin@^1.12.0:
version "1.12.0"
resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.12.0.tgz#a11d3eb565602190748b1f95ecc8590b0f7dcbb4"
integrity sha512-KeczzHl2sATPQUx1gzo+EnUkmN4VmGBYRRVOZSGvGITE9rGHRDGqft6ONceP3vgXcyJ2XjX5axG5jMWUwNCYLw==
dependencies:
acorn "^8.12.1"
chokidar "^3.6.0"
webpack-sources "^3.2.3"
webpack-virtual-modules "^0.6.2"
unset-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
@ -9006,6 +9235,11 @@ vue-demi@>=0.13.0, vue-demi@>=0.14.8:
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.8.tgz#00335e9317b45e4a68d3528aaf58e0cec3d5640a"
integrity sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==
vue-demi@^0.14.6:
version "0.14.10"
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04"
integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==
vue-eslint-parser@^8.0.0, vue-eslint-parser@^8.0.1:
version "8.3.0"
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-8.3.0.tgz#5d31129a1b3dd89c0069ca0a1c88f970c360bd0d"
@ -9066,9 +9300,9 @@ vue-jest@^3.0.7:
vue-template-es2015-compiler "^1.6.0"
vue-loading-overlay@^3.4.2:
version "3.4.2"
resolved "https://registry.yarnpkg.com/vue-loading-overlay/-/vue-loading-overlay-3.4.2.tgz#34792a83218df1d35dff50121ce9fac2114f1c38"
integrity sha512-xcB+NPjl76eA0uggm707x3ZFgrNosZXpynHipyS3K+rrK1NztOV49R1LY+/4ij5W1KYANp7eRI2EIHrxCpmWAw==
version "3.4.3"
resolved "https://registry.yarnpkg.com/vue-loading-overlay/-/vue-loading-overlay-3.4.3.tgz#ea14a0cb0d94ac5c91e45f90c21da6233b3cf1b5"
integrity sha512-Q4+RNnI6+szylJ98Abnp9CUDagKphZMt7okznGu1m7tidZX5b9u+a+De6uktWa5WULu/as+IsrWVR8lpmbDDOA==
vue-router@^4.4.0:
version "4.4.0"
@ -9082,6 +9316,11 @@ vue-template-es2015-compiler@^1.6.0:
resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825"
integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==
vue-timer-hook@^1.0.84:
version "1.0.84"
resolved "https://registry.yarnpkg.com/vue-timer-hook/-/vue-timer-hook-1.0.84.tgz#96acd9a74297bd003ffb6983a5c660bc8260cee4"
integrity sha512-OcHWYO8WD/XcGHdEqMkBI1Vj8m+OnXONrcmZvLcL3Gc6Js5LEs3UJ0eg1akVjNB0cXHishEmrmrhK7PZ+iULww==
vue-timers@^2.0.4:
version "2.0.4"
resolved "https://registry.yarnpkg.com/vue-timers/-/vue-timers-2.0.4.tgz#7e1c443abf2109db5eeab6e62b0f5a47e94cf70b"
@ -9154,7 +9393,7 @@ webpack-sources@^3.2.3:
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
webpack-virtual-modules@^0.6.1:
webpack-virtual-modules@^0.6.1, webpack-virtual-modules@^0.6.2:
version "0.6.2"
resolved "https://registry.yarnpkg.com/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz#057faa9065c8acf48f24cb57ac0e77739ab9a7e8"
integrity sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==
@ -9321,6 +9560,11 @@ yargs@^15.4.1:
y18n "^4.0.0"
yargs-parser "^18.1.2"
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
yup@^1.3.2, yup@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/yup/-/yup-1.4.0.tgz#898dcd660f9fb97c41f181839d3d65c3ee15a43e"