frontend - login page updates

This commit is contained in:
Mateusz Michałowski 2024-07-23 08:16:12 +02:00
parent 3cde113249
commit 89b9b1a535
25 changed files with 1043 additions and 492 deletions

View File

@ -19,10 +19,11 @@
"@babel/node": "^7.13.13",
"@babel/preset-env": "^7.13.12",
"@vee-validate/rules": "^4.13.2",
"@vee-validate/yup": "^4.13.2",
"@vitejs/plugin-vue": "3.2.0",
"@vue/apollo-option": "^4.0.0",
"@vue/test-utils": "^1.1.3",
"@vue/compat": "^3.4.31",
"@vue/test-utils": "^1.1.3",
"apollo-boost": "^0.4.9",
"autoprefixer": "^10.4.19",
"babel-core": "^7.0.0-bridge.0",
@ -70,7 +71,8 @@
"vue-timers": "^2.0.4",
"vue2-transitions": "^0.2.3",
"vuex": "^4.1.0",
"vuex-persistedstate": "^4.1.0"
"vuex-persistedstate": "^4.1.0",
"yup": "^1.4.0"
},
"devDependencies": {
"@apollo/client": "^3.10.8",
@ -88,6 +90,7 @@
"stylelint": "^14.5.3",
"stylelint-config-recommended-vue": "^1.3.0",
"stylelint-config-standard-scss": "^3.0.0",
"unplugin-vue-components": "^0.27.3",
"vue-html-webpack-plugin": "^3.2.2"
},
"postcss": {

View File

@ -979,3 +979,5 @@ $btn-border-radius-sm: $input-border-radius !default;
// Import Bootstrap variable defaults
@import "bootstrap/scss/variables";
@import "gradido-custom/functions";

View File

@ -13,8 +13,8 @@ $box-shadow-sm: 0 0 0.5rem rgba($gray-600, 0.075) !default;
$box-shadow: 0 0 2rem 0 rgba($gray-600, 0.15) !default;
$box-shadow-lg: 0 0 3rem rgba($gray-600, 0.175) !default;
$component-active-color: $white !default;
$component-active-bg: theme-color("primary") !default;
$component-active-border-color: theme-color("primary") !default;
$component-active-bg: $primary !default;
$component-active-border-color: $primary !default;
$component-hover-color: $gray-300 !default;
$component-hover-bg: $gray-300 !default;
$component-hover-border-color: $gray-300 !default;

View File

@ -23,7 +23,7 @@ $custom-control-indicator-checked-border-color: $component-active-border-color !
$custom-control-indicator-checked-box-shadow: $custom-control-indicator-box-shadow !default;
// $custom-control-indicator-checked-disabled-bg: rgb(theme-color("primary") 0.5) !default;
$custom-control-indicator-checked-disabled-bg: theme-color("primary") !default;
$custom-control-indicator-checked-disabled-bg: $primary !default;
$custom-control-indicator-disabled-bg: $gray-200 !default;
$custom-control-label-disabled-color: $gray-600 !default;

View File

@ -2,4 +2,4 @@
$custom-toggle-width: 50px !default;
$custom-toggle-slider-bg: $gray-200 !default;
$custom-toggle-checked-bg: theme-color("primary") !default;
$custom-toggle-checked-bg: $primary !default;

View File

@ -12,9 +12,9 @@ $datepicker-disabled-cell-color: $gray-300 !default;
$datepicker-disabled-old-new-color: $gray-500 !default;
$datepicker-header-cell-border-radius: $border-radius !default;
$datepicker-active-color: $white !default;
$datepicker-active-background: theme-color("primary") !default;
$datepicker-active-background: $primary !default;
$datepicker-active-box-shadow: none !default;
$datepicker-range-background: theme-color("primary") !default;
$datepicker-range-background: $primary !default;
$datepicker-range-cell-focused-background: color.adjust($datepicker-range-background, $lightness: -5%);
$datepicker-range-color: $white !default;
$datepicker-range-highlighted-bg: $gray-200 !default;

View File

@ -3,7 +3,7 @@
$footer-padding-y: 2.5rem;
$footer-padding-x: 0;
$footer-link-font-size: 0.85rem !default;
$footer-bg: theme-color("secondary") !default;
$footer-bg: $secondary !default;
$footer-color: $gray-600 !default;
$footer-link-color: $gray-600 !default;
$footer-link-hover-color: $gray-700 !default;

View File

@ -2,6 +2,6 @@
@use "sass:color";
$form-feedback-valid-bg: color.adjust($success, $lightness: 15%) !default;
$form-feedback-valid-color: theme-color("success") !default;
$form-feedback-valid-color: $success !default;
$form-feedback-invalid-bg: color.adjust($warning, $lightness: 15%) !default;
$form-feedback-invalid-color: theme-color("warning") !default;
$form-feedback-invalid-color: $warning !default;

View File

@ -0,0 +1,3 @@
@function theme-color($key: "primary") {
@return #172b4d;
}

View File

@ -4,17 +4,17 @@
$nav-link-padding-y: 0.25rem !default;
$nav-link-padding-x: 0.75rem !default;
$nav-link-color: $gray-700 !default;
$nav-link-hover-color: theme-color("primary") !default;
$nav-link-hover-color: $primary !default;
$nav-link-disabled-color: $gray-600 !default;
$nav-pills-padding-y: 0.75rem !default;
$nav-pills-padding-x: 1rem !default;
$nav-pills-space-x: 1rem !default;
$nav-pills-bg: $white !default;
$nav-pills-border-width: 1px !default;
$nav-pills-border-color: theme-color("primary") !default;
$nav-pills-border-color: $primary !default;
$nav-pills-border-radius: $border-radius !default;
$nav-pills-link-color: theme-color("primary") !default;
$nav-pills-link-hover-color: color.adjust(theme-color("primary"), $lightness: -5%) !default;
$nav-pills-link-active-color: color-yiq(theme-color("primary")) !default;
$nav-pills-link-active-bg: theme-color("primary") !default;
$nav-pills-link-color: $primary !default;
$nav-pills-link-hover-color: color.adjust($primary, $lightness: -5%) !default;
$nav-pills-link-active-color: color-yiq($primary) !default;
$nav-pills-link-active-bg: $primary !default;
$nav-pills-box-shadow: $btn-box-shadow !default;

View File

@ -8,7 +8,7 @@ $noui-target-box-shadow: inset 0 1px 2px rgb(90 97 105 / 10%) !default;
$noui-slider-connect-bg: $primary !default;
$noui-slider-connect-disabled-bg: #b2b2b2 !default;
$noui-handle-width: 15px !default;
$noui-handle-bg: theme-color("primary") !default;
$noui-handle-bg: $primary !default;
$noui-handle-border: 0 !default;
$noui-handle-border-radius: 100% !default;
$noui-origin-border-radius: 2px !default;

View File

@ -17,10 +17,10 @@ $table-head-font-weight: $font-weight-bold !default;
$table-head-text-transform: uppercase !default;
$table-head-letter-spacing: 1px !default;
$table-body-font-size: 0.8125rem !default;
$table-dark-bg: theme-color("default") !default;
$table-dark-bg: $default !default;
$table-dark-accent-bg: rgba($white, 0.05) !default;
$table-dark-hover-bg: rgba($white, 0.075) !default;
$table-dark-border-color: color.adjust(theme-color("default"), $lightness: 7%) !default;
$table-dark-border-color: color.adjust($default, $lightness: 7%) !default;
$table-dark-color: $body-bg !default;
$table-dark-head-bg: color.adjust(theme-color("default"), $lightness: 4%) !default;
$table-dark-head-color: color.adjust(theme-color("default"), $lightness: 35%) !default;
$table-dark-head-bg: color.adjust($default, $lightness: 4%) !default;
$table-dark-head-color: color.adjust($default, $lightness: 35%) !default;

View File

@ -1,12 +1,15 @@
// Bootstrap (4.5.3) functions
@import "bootstrap/scss/functions";
@import "bootstrap/scss/variables";
@import "custom/variables";
// @import "~bootstrap/scss/variables"; wird am
// ende der custom/variables angehangen
// Bootstrap (4.5.3) mixins
@import "bootstrap/scss/maps";
@import "bootstrap/scss/mixins";
// Bootstrap (4.5.3) components
@ -19,15 +22,15 @@
@import "bootstrap/scss/card";
@import "bootstrap/scss/carousel";
@import "bootstrap/scss/close";
@import "bootstrap/scss/code";
@import "bootstrap/scss/custom-forms";
//@import "bootstrap/scss/code";
//@import "bootstrap/scss/custom-forms";
// @import "~bootstrap/scss/dropdown";
@import "bootstrap/scss/forms";
// @import "~bootstrap/scss/functions";
@import "bootstrap/scss/grid";
@import "bootstrap/scss/input-group";
//@import "bootstrap/scss/input-group";
@import "bootstrap/scss/list-group";
// @import "~bootstrap/scss/mixins";
@ -35,7 +38,7 @@
@import "bootstrap/scss/nav";
@import "bootstrap/scss/navbar";
@import "bootstrap/scss/pagination";
@import "bootstrap/scss/print";
//@import "bootstrap/scss/print";
@import "bootstrap/scss/progress";
@import "bootstrap/scss/reboot";
@import "bootstrap/scss/tables";
@ -44,12 +47,12 @@
@import "bootstrap/scss/transitions";
@import "bootstrap/scss/type";
@import "bootstrap/scss/utilities";
@import "bootstrap/scss/variables";
//@import "bootstrap/scss/variables";
@import "bootstrap/scss/bootstrap-grid";
@import "bootstrap/scss/bootstrap-reboot";
@import "bootstrap/scss/bootstrap";
// Bootstrap-vue (2.21.1) scss
@import "bootstrap-vue/src/index";
//@import "bootstrap-vue/src/index";
@import "gradido-template";
@import "gradido-template-dark";

View File

@ -1,19 +1,19 @@
<template>
<div>
<b-carousel :interval="13000">
<b-carousel-slide img-src="/img/template/Foto_01_2400_small.jpg">
<BCarousel :interval="13000" ride="carousel">
<BCarouselSlide img-src="/img/template/Foto_01_2400_small.jpg">
<div class="caption-first-text">{{ $t('auth.left.gratitude') }}</div>
<div class="caption-second-text">{{ $t('auth.left.oneGratitude') }}</div>
</b-carousel-slide>
<b-carousel-slide img-src="/img/template/Foto_02_2400_small.jpg">
</BCarouselSlide>
<BCarouselSlide img-src="/img/template/Foto_02_2400_small.jpg">
<div class="caption-first-text">{{ $t('auth.left.dignity') }}</div>
<div class="caption-second-text">{{ $t('auth.left.oneDignity') }}</div>
</b-carousel-slide>
<b-carousel-slide img-src="/img/template/Foto_03_2400_small.jpg">
</BCarouselSlide>
<BCarouselSlide img-src="/img/template/Foto_03_2400_small.jpg">
<div class="caption-first-text">{{ $t('auth.left.donation') }}</div>
<div class="caption-second-text">{{ $t('auth.left.oneDonation') }}</div>
</b-carousel-slide>
</b-carousel>
</BCarouselSlide>
</BCarousel>
</div>
</template>

View File

@ -1,29 +1,24 @@
<template>
<div class="auth-header position-sticky">
<b-navbar :toggleable="false" class="pr-4">
<b-navbar-brand class="d-none d-lg-block">
<b-img
class="position-absolute ml--3 mt-lg--2 mt-3 p-2 zindex1000"
:src="logo"
width="200"
alt="Logo"
/>
<b-img
<BNavbar :toggleable="false" :container="false" class="d-flex">
<BNavbarBrand class="d-none d-lg-block">
<BImg class="position-absolute ml--3 mt-lg--2 p-2" :src="logo" width="200" alt="Logo" />
<BImg
class="mt--3 ml--3"
:src="background_header"
width="230"
alt="Background Image"
></b-img>
</b-navbar-brand>
<b-img class="sheet-img position-absolute d-block d-lg-none zindex1000" :src="sheet"></b-img>
<b-collapse id="nav-collapse" is-nav class="ml-5">
<b-navbar-nav class="ml-auto d-none d-lg-flex" right>
<b-nav-item :to="register" class="authNavbar ml-lg-5">{{ $t('signup') }}</b-nav-item>
></BImg>
</BNavbarBrand>
<BImg class="sheet-img position-absolute d-block d-lg-none zindex1000" :src="sheet"></BImg>
<BCollapse id="nav-collapse" is-nav>
<BNavbarNav class="ml-auto d-none d-lg-flex" right>
<BNavItem :to="register" class="authNavbar ml-lg-5">{{ $t('signup') }}</BNavItem>
<span class="d-none d-lg-block mt-1">{{ $t('math.pipe') }}</span>
<b-nav-item :to="login" class="authNavbar">{{ $t('signin') }}</b-nav-item>
</b-navbar-nav>
</b-collapse>
</b-navbar>
<BNavItem :to="login" class="authNavbar">{{ $t('signin') }}</BNavItem>
</BNavbarNav>
</BCollapse>
</BNavbar>
</div>
</template>
@ -43,18 +38,30 @@ export default {
}
</script>
<style lang="scss">
.authNavbar > .nav-link {
<style scoped lang="scss">
.authNavbar {
display: flex;
align-content: center;
> * {
text-decoration: none;
}
}
.authNavbar > :deep(.nav-link) {
color: #0e79bc !important;
}
.authNavbar > .router-link-exact-active {
.authNavbar > :deep(.router-link-exact-active) {
color: #383838 !important;
}
.auth-header {
font-family: 'Open Sans', sans-serif !important;
height: 150px;
z-index: 1;
}
:deep(#nav-collapse) {
justify-content: flex-end;
}
.sheet-img {

View File

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

View File

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

View File

@ -13,7 +13,7 @@
</span>
<b-icon icon="caret-down-fill" aria-hidden="true"></b-icon>
</div>
<b-collapse id="collapse-1" class="mt-4">
<BCollapse id="collapse-1" class="mt-4">
<span
v-for="(lang, index) in locales"
@click.prevent="saveLocale(lang.code)"
@ -35,7 +35,7 @@
{{ locales.length - 1 > index ? $t('math.pipe') : '' }}
</span>
</span>
</b-collapse>
</BCollapse>
</div>
</template>

View File

@ -235,6 +235,7 @@ const dateTimeFormats = {
export default createI18n({
locale: 'en',
legacy: false,
fallbackLocale: 'en',
messages: { de, en, es, fr, tr, nl },
numberFormats,

View File

@ -1,48 +1,52 @@
<template>
<div class="auth-template">
<div class="h-100 align-middle">
<auth-navbar class="zindex10" />
<auth-navbar class="index10" />
<div class="left-content-box position-fixed d-none d-lg-block">
<div class="bg-img-box position-absolute w-100">
<auth-carousel class="carousel" />
</div>
<div class="bg-txt-box position-relative d-none d-lg-block text-center align-self-center">
<b-link :href="`https://gradido.net/${$i18n.locale}`" target="_blank">
<b-button variant="gradido">
<BLink :href="`https://gradido.net/${$i18n.locale}`" target="_blank">
<BButton variant="gradido">
{{ $t('auth.left.learnMore') }}
</b-button>
</b-link>
</BButton>
</BLink>
</div>
</div>
<b-row class="justify-content-md-center justify-content-lg-end">
<b-col sm="12" md="8" lg="6" class="zindex1000">
<BRow class="justify-content-md-center justify-content-lg-end">
<BCol sm="12" md="8" lg="6" class="zindex1000">
<div class="ml-3 ml-sm-4 mr-3 mr-sm-4">
<b-row class="d-none d-md-block d-lg-none">
<b-col class="mb--4">
<BRow class="d-none d-md-block d-lg-none">
<BCol class="mb--4">
<auth-navbar-small />
</b-col>
</b-row>
<b-row class="mt-0 mt-md-5 pl-2 pl-md-0 pl-lg-0">
<b-col lg="9" md="9" sm="12">
</BCol>
</BRow>
<BRow class="mt-0 mt-md-5 pl-2 pl-md-0 pl-lg-0">
<BCol lg="9" md="9" sm="12">
<div class="mb--2">{{ $t('welcome') }}</div>
<div class="h1 mb-0">{{ communityName }}</div>
<div class="mb-0">{{ $t('1000thanks') }}</div>
</b-col>
<b-col cols="3" class="text-right d-none d-sm-none d-md-inline">
<b-avatar src="/img/brand/gradido_coin●.png" size="6rem"></b-avatar>
</b-col>
</b-row>
<b-card no-body ref="pageFontSize" class="border-0 mt-4 gradido-custom-background">
<b-row class="p-4">
<b-col cols="10">
</BCol>
<BCol cols="3" class="text-right d-none d-sm-none d-md-inline">
<BAvatar
src="/img/brand/gradido_coin●.png"
size="6rem"
variant="transparent"
></BAvatar>
</BCol>
</BRow>
<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" />
</b-col>
<b-col cols="2" class="text-right">
</BCol>
<BCol cols="2" class="text-right">
<div id="popover-target-1" class="pointer">
<b-img src="/img/svg/type.svg" width="19" class="svgType"></b-img>
<BImg src="/img/svg/type.svg" width="19" class="svgType"></BImg>
</div>
<b-popover
<Bpopover
target="popover-target-1"
triggers="click"
placement="top"
@ -55,27 +59,31 @@
{{ $t('math.pipe') }}
<span class="pointer" @click="setTextSize(1.25)">{{ $t('125') }}</span>
</div>
</b-popover>
</b-col>
</b-row>
<b-row class="d-inline d-sm-inline d-md-none d-lg-none mb-3">
<b-col class="text-center">
<b-avatar src="/img/brand/gradido_coin●.png" size="6rem"></b-avatar>
<b-row>
<b-col class="zindex1000 d-flex justify-content-center">
</Bpopover>
</BCol>
</BRow>
<BRow class="d-inline d-sm-inline d-md-none d-lg-none mb-3">
<BCol class="text-center">
<BAvatar
src="/img/brand/gradido_coin●.png"
size="6rem"
bg-variant="transparent"
></BAvatar>
<BRow>
<BCol class="zindex1000 d-flex justify-content-center">
<auth-navbar-small />
</b-col>
</b-row>
</b-col>
</b-row>
<b-card-body class="">
</BCol>
</BRow>
</BCol>
</BRow>
<BCardBody class="">
<router-view></router-view>
</b-card-body>
</b-card>
</BCardBody>
</BCard>
</div>
<auth-footer v-if="!$route.meta.hideFooter" class="pr-5 mb-5"></auth-footer>
</b-col>
</b-row>
</BCol>
</BRow>
</div>
</div>
</template>

View File

@ -1,4 +1,6 @@
import { createApp } from 'vue'
import '@/assets/scss/gradido.scss'
// import DashboardPlugin from './plugins/dashboard-plugin'
import App from './App'
import i18n from './i18n.js'
@ -23,6 +25,7 @@ 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 GlobalComponents from '@/plugins/globalComponents'
import GlobalDirectives from '@/plugins/globalDirectives'
import PortalVue from 'portal-vue'
@ -53,6 +56,12 @@ const filters = loadFilters(i18n)
app.filter('amount', filters.amount)
app.filter('GDD', filters.GDD)
//TODO it will be used in future
// app.config.globalProperties.$filters = {
// GDD: filters.GDD,
// amount: filters.amount,
// }
loadAllRules(i18n, apolloProvider.defaultClient)
addNavigationGuards(router, store, apolloProvider.defaultClient)

View File

@ -1,140 +1,275 @@
<!--<template>-->
<!-- <div class="login-form">-->
<!-- <BContainer v-if="enterData">-->
<!-- <div class="pb-5" align="center">{{ $t('gdd_per_link.isFree') }}</div>-->
<!-- <validation-observer ref="observer" v-slot="{ handleSubmit, valid }">-->
<!-- <BForm @submit.stop.prevent="handleSubmit(onSubmit)">-->
<!-- <BRow>-->
<!-- <BCol sm="12" md="12" lg="6">-->
<!-- <input-email-->
<!-- v-model="form.email"-->
<!-- :name="$t('form.email')"-->
<!-- :label="$t('form.email')"-->
<!-- :placeholder="$t('form.email')"-->
<!-- />-->
<!-- </BCol>-->
<!-- <BCol sm="12" md="12" lg="6">-->
<!-- <input-password-->
<!-- :label="$t('form.password')"-->
<!-- :placeholder="$t('form.password')"-->
<!-- :name="$t('form.password')"-->
<!-- v-model="form.password"-->
<!-- ></input-password>-->
<!-- </BCol>-->
<!-- </BRow>-->
<!-- <BRow>-->
<!-- <BCol class="d-flex justify-content-end mb-4 mb-lg-0">-->
<!-- <router-link to="/forgot-password" data-test="forgot-password-link">-->
<!-- {{ $t('settings.password.forgot_pwd') }}-->
<!-- </router-link>-->
<!-- </BCol>-->
<!-- </BRow>-->
<!-- <BRow>-->
<!-- <BCol cols="12" lg="6">-->
<!-- <BButton-->
<!-- type="submit"-->
<!-- :variant="valid ? 'gradido' : 'gradido-disable'"-->
<!-- block-->
<!-- :disabled="!valid"-->
<!-- >-->
<!-- {{ $t('login') }}-->
<!-- </BButton>-->
<!-- </BCol>-->
<!-- </BRow>-->
<!-- </BForm>-->
<!-- </validation-observer>-->
<!-- </BContainer>-->
<!-- <BContainer v-else>-->
<!-- <message-->
<!-- :headline="$t('message.errorTitle')"-->
<!-- :subtitle="errorSubtitle"-->
<!-- :buttonText="$t('settings.password.reset')"-->
<!-- :linkTo="errorLinkTo"-->
<!-- />-->
<!-- </BContainer>-->
<!-- </div>-->
<!--</template>-->
<template>
<div class="login-form">
<b-container v-if="enterData">
{{ isValidating }}
<BContainer v-if="enterData">
<div class="pb-5" align="center">{{ $t('gdd_per_link.isFree') }}</div>
<validation-observer ref="observer" v-slot="{ handleSubmit, valid }">
<b-form @submit.stop.prevent="handleSubmit(onSubmit)">
<b-row>
<b-col sm="12" md="12" lg="6">
<input-email
v-model="form.email"
:name="$t('form.email')"
:label="$t('form.email')"
:placeholder="$t('form.email')"
></input-email>
</b-col>
<b-col sm="12" md="12" lg="6">
<input-password
:label="$t('form.password')"
:placeholder="$t('form.password')"
:name="$t('form.password')"
v-model="form.password"
></input-password>
</b-col>
</b-row>
<b-row>
<b-col class="d-flex justify-content-end mb-4 mb-lg-0">
<router-link to="/forgot-password" data-test="forgot-password-link">
{{ $t('settings.password.forgot_pwd') }}
</router-link>
</b-col>
</b-row>
<b-row>
<b-col cols="12" lg="6">
<b-button
type="submit"
:variant="valid ? 'gradido' : 'gradido-disable'"
block
:disabled="!valid"
>
{{ $t('login') }}
</b-button>
</b-col>
</b-row>
</b-form>
</validation-observer>
</b-container>
<b-container v-else>
<form @submit.prevent="onSubmit">
<BRow>
<BCol sm="12" md="12" lg="6">
<input-email :name="$t('form.email')" />
</BCol>
<BCol sm="12" md="12" lg="6">
<input-password :name="$t('form.password')" />
</BCol>
</BRow>
<BRow>
<BCol class="d-flex justify-content-end mb-4 mb-lg-0">
<router-link to="/forgot-password" data-test="forgot-password-link">
{{ $t('settings.password.forgot_pwd') }}
</router-link>
</BCol>
</BRow>
<BRow>
<BCol cols="12" lg="6">
<BButton
type="submit"
:variant="isValidating ? 'gradido' : 'gradido-disable'"
block
:disabled="!isValidating"
>
{{ $t('login') }}
</BButton>
</BCol>
</BRow>
</form>
</BContainer>
<BContainer v-else>
<message
:headline="$t('message.errorTitle')"
:subtitle="errorSubtitle"
:buttonText="$t('settings.password.reset')"
:linkTo="errorLinkTo"
/>
</b-container>
</BContainer>
</div>
</template>
<script>
<!--<script>-->
<!--import InputPassword from '@/components/Inputs/InputPassword'-->
<!--import InputEmail from '@/components/Inputs/InputEmail'-->
<!--import Message from '@/components/Message/Message'-->
<!--import { login } from '@/graphql/mutations'-->
<!--export default {-->
<!-- name: 'Login',-->
<!-- components: {-->
<!-- InputPassword,-->
<!-- InputEmail,-->
<!-- Message,-->
<!-- },-->
<!-- data() {-->
<!-- return {-->
<!-- form: {-->
<!-- email: '',-->
<!-- password: '',-->
<!-- },-->
<!-- passwordVisible: false,-->
<!-- showPageMessage: false,-->
<!-- errorReason: null,-->
<!-- errorSubtitle: '',-->
<!-- errorLinkTo: '',-->
<!-- }-->
<!-- },-->
<!-- methods: {-->
<!-- async onSubmit() {-->
<!-- const loader = this.$loading.show({-->
<!-- container: this.$refs.submitButton,-->
<!-- })-->
<!-- this.$root.$bvToast.hide()-->
<!-- this.$apollo-->
<!-- .mutate({-->
<!-- mutation: login,-->
<!-- variables: {-->
<!-- email: this.form.email,-->
<!-- password: this.form.password,-->
<!-- publisherId: this.$store.state.publisherId,-->
<!-- },-->
<!-- })-->
<!-- .then(async (result) => {-->
<!-- const {-->
<!-- data: { login },-->
<!-- } = result-->
<!-- this.$store.dispatch('login', login)-->
<!-- this.$store.commit('email', this.form.email)-->
<!-- await loader.hide()-->
<!-- if (this.$route.params.code) {-->
<!-- this.$router.push(`/redeem/${this.$route.params.code}`)-->
<!-- } else {-->
<!-- this.$router.push(this.$store.state.redirectPath)-->
<!-- }-->
<!-- })-->
<!-- .catch((error) => {-->
<!-- if (error.message.includes('User email not validated')) {-->
<!-- this.showPageMessage = true-->
<!-- this.errorSubtitle = this.$t('message.activateEmail')-->
<!-- this.errorLinkTo = '/forgot-password'-->
<!-- this.toastError(this.$t('error.no-account'))-->
<!-- } else if (error.message.includes('User has no password set yet')) {-->
<!-- this.showPageMessage = true-->
<!-- this.errorSubtitle = this.$t('message.unsetPassword')-->
<!-- this.errorLinkTo = '/reset-password/login'-->
<!-- this.toastError(this.$t('error.no-account'))-->
<!-- } else if (error.message.includes('No user with this credentials')) {-->
<!-- this.toastError(this.$t('error.no-user'))-->
<!-- } else {-->
<!-- this.toastError(this.$t('error.unknown-error') + error.message)-->
<!-- }-->
<!-- loader.hide()-->
<!-- })-->
<!-- },-->
<!-- },-->
<!-- computed: {-->
<!-- enterData() {-->
<!-- return !this.showPageMessage-->
<!-- },-->
<!-- },-->
<!--}-->
<!--</script>-->
<script setup>
import InputPassword from '@/components/Inputs/InputPassword'
import InputEmail from '@/components/Inputs/InputEmail'
import Message from '@/components/Message/Message'
import { login } from '@/graphql/mutations'
import { ref, computed } from 'vue'
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'
export default {
name: 'Login',
components: {
InputPassword,
InputEmail,
Message,
},
data() {
return {
form: {
email: '',
password: '',
// 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 form = ref({
email: '',
password: '',
})
// const { handleSubmit, isValid } = useForm({
// validationSchema: schema,
// })
//
const { values, errors, handleSubmit, isValidating } = useForm({ validationSchema: schema })
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 onSubmit = handleSubmit(async (values) => {
const loader = this.$loading.show({
container: this.$refs.submitButton,
})
this.$root.$bvToast.hide()
try {
const result = await this.$apollo.mutate({
mutation: login,
variables: {
email: values.email,
password: values.password,
publisherId: store.state.publisherId,
},
passwordVisible: false,
showPageMessage: false,
errorReason: null,
errorSubtitle: '',
errorLinkTo: '',
})
const {
data: { login },
} = result
await store.dispatch('login', login)
store.commit('email', values.email)
await loader.hide()
if (route.params.code) {
router.push(`/redeem/${route.params.code}`)
} else {
router.push(store.state.redirectPath)
}
},
methods: {
async onSubmit() {
const loader = this.$loading.show({
container: this.$refs.submitButton,
})
this.$root.$bvToast.hide()
this.$apollo
.mutate({
mutation: login,
variables: {
email: this.form.email,
password: this.form.password,
publisherId: this.$store.state.publisherId,
},
})
.then(async (result) => {
const {
data: { login },
} = result
this.$store.dispatch('login', login)
this.$store.commit('email', this.form.email)
await loader.hide()
if (this.$route.params.code) {
this.$router.push(`/redeem/${this.$route.params.code}`)
} else {
this.$router.push(this.$store.state.redirectPath)
}
})
.catch((error) => {
if (error.message.includes('User email not validated')) {
this.showPageMessage = true
this.errorSubtitle = this.$t('message.activateEmail')
this.errorLinkTo = '/forgot-password'
this.toastError(this.$t('error.no-account'))
} else if (error.message.includes('User has no password set yet')) {
this.showPageMessage = true
this.errorSubtitle = this.$t('message.unsetPassword')
this.errorLinkTo = '/reset-password/login'
this.toastError(this.$t('error.no-account'))
} else if (error.message.includes('No user with this credentials')) {
this.toastError(this.$t('error.no-user'))
} else {
this.toastError(this.$t('error.unknown-error') + error.message)
}
loader.hide()
})
},
},
computed: {
enterData() {
return !this.showPageMessage
},
},
}
} 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'))
} 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'))
} else if (error.message.includes('No user with this credentials')) {
this.toastError(t('error.no-user'))
} else {
this.toastError(t('error.unknown-error') + error.message)
}
loader.hide()
}
})
const enterData = computed(() => !showPageMessage.value)
// const isFormValid = computed(() => isValid.value)
</script>
<style scoped>
.btn-gradido {

View File

@ -25,151 +25,152 @@ export const loadAllRules = (i18nCallback, apollo) => {
},
})
defineRule('email', {
...email,
// eslint-disable-next-line @intlify/vue-i18n/no-missing-keys
message: (_, values) => i18nCallback.t('validations.messages.email', values),
defineRule('email', (value) => {
const isValid = email(value)
if (!isValid) {
return i18nCallback.t('validations.messages.email', value)
}
return true
})
defineRule('required', {
...required,
// eslint-disable-next-line @intlify/vue-i18n/no-missing-keys
message: (_, values) => i18nCallback.t('validations.messages.required', values),
defineRule('required', (value) => {
const valueExists = required(value)
if (!valueExists) {
return i18nCallback.t('validations.messages.required', value)
}
return true
})
defineRule('min', {
...min,
// eslint-disable-next-line @intlify/vue-i18n/no-missing-keys
message: (_, values) => i18nCallback.t('validations.messages.min', values),
defineRule('min', (value, limit) => {
return min(value, limit) ? true : i18nCallback.t('validations.messages.min', value)
})
defineRule('max', {
...max,
// eslint-disable-next-line @intlify/vue-i18n/no-missing-keys
message: (_, values) => i18nCallback.t('validations.messages.max', values),
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('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('containsUppercaseCharacter', (value) => {
const isValid = !!value.match(/[A-Z]+/)
if (!isValid) {
i18nCallback.t('site.signup.uppercase', { value })
}
})
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', {
validate(value) {
return !!value.match(/[a-z]+/)
},
message: (_, values) => i18nCallback.t('site.signup.lowercase', values),
})
defineRule('containsUppercaseCharacter', {
validate(value) {
return !!value.match(/[A-Z]+/)
},
message: (_, values) => i18nCallback.t('site.signup.uppercase', values),
})
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', {
// 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),
// })
}

View File

@ -1,12 +1,15 @@
import { defineConfig } from 'vite'
import commonjs from 'vite-plugin-commonjs'
import vue from '@vitejs/plugin-vue'
import Components from 'unplugin-vue-components/vite'
import { BootstrapVueNextResolver } from 'bootstrap-vue-next'
const path = require('path')
// https://vitejs.dev/config/
export default defineConfig({
server: {
host: '0.0.0.0',
port: 3000,
},
resolve: {
@ -27,6 +30,9 @@ export default defineConfig({
},
},
}),
Components({
resolvers: [BootstrapVueNextResolver()],
}),
commonjs(),
],
})

View File

@ -2,6 +2,11 @@
# yarn lockfile v1
"@antfu/utils@^0.7.10":
version "0.7.10"
resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-0.7.10.tgz#ae829f170158e297a9b6a28f161a8e487d00814d"
integrity sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==
"@apollo/client@^3.10.8":
version "3.10.8"
resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.10.8.tgz#96b1548818e45fac752ec2bd318e5466d9ca26b5"
@ -1758,6 +1763,15 @@
"@nodelib/fs.scandir" "2.1.4"
fastq "^1.6.0"
"@rollup/pluginutils@^5.1.0":
version "5.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-5.1.0.tgz#7e53eddc8c7f483a4ad0b94afb1f7f5fd3c771e0"
integrity sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==
dependencies:
"@types/estree" "^1.0.0"
estree-walker "^2.0.2"
picomatch "^2.3.1"
"@sinonjs/commons@^1.7.0":
version "1.8.2"
resolved "https://registry.yarnpkg.com/@sinonjs/commons/-/commons-1.8.2.tgz#858f5c4b48d80778fde4b9d541f27edc0d56488b"
@ -1812,6 +1826,11 @@
dependencies:
"@babel/types" "^7.3.0"
"@types/estree@^1.0.0":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
"@types/graceful-fs@^4.1.2":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@types/graceful-fs/-/graceful-fs-4.1.5.tgz#21ffba0d98da4350db64891f92a9e5db3cdb4e15"
@ -1975,6 +1994,15 @@
dependencies:
vee-validate "4.13.2"
"@vee-validate/yup@^4.13.2":
version "4.13.2"
resolved "https://registry.yarnpkg.com/@vee-validate/yup/-/yup-4.13.2.tgz#502f176317a67a859f056adefc77884b00c9e3a1"
integrity sha512-ai0UL46S3GKO8wxnjTN6ksbxmpRrgOxKZlVO0GVqMAF52ZXW92wcADk5qUtuuW+kWe3cePuK6MH305J+kT9scw==
dependencies:
type-fest "^4.8.3"
vee-validate "4.13.2"
yup "^1.3.2"
"@vitejs/plugin-vue@3.2.0":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-3.2.0.tgz#a1484089dd85d6528f435743f84cdd0d215bbb54"
@ -2217,16 +2245,16 @@ 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:
version "8.12.1"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248"
integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
acorn@^8.5.0, acorn@^8.7.0:
version "8.7.0"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.7.0.tgz#90951fde0f8f09df93549481e5fc141445b791cf"
integrity sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==
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==
ajv-keywords@^3.5.2:
version "3.5.2"
resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d"
@ -2892,6 +2920,13 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0"
concat-map "0.0.1"
brace-expansion@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae"
integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==
dependencies:
balanced-match "^1.0.0"
braces@^2.3.1:
version "2.3.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729"
@ -3094,6 +3129,21 @@ char-regex@^1.0.2:
optionalDependencies:
fsevents "~2.3.2"
chokidar@^3.6.0:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
dependencies:
anymatch "~3.1.2"
braces "~3.0.2"
glob-parent "~5.1.2"
is-binary-path "~2.1.0"
is-glob "~4.0.1"
normalize-path "~3.0.0"
readdirp "~3.6.0"
optionalDependencies:
fsevents "~2.3.2"
ci-info@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
@ -3259,6 +3309,11 @@ condense-newlines@^0.2.1:
is-whitespace "^0.3.0"
kind-of "^3.0.2"
confbox@^0.1.7:
version "0.1.7"
resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.7.tgz#ccfc0a2bcae36a84838e83a3b7f770fb17d6c579"
integrity sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==
config-chain@^1.1.12:
version "1.1.12"
resolved "https://registry.yarnpkg.com/config-chain/-/config-chain-1.1.12.tgz#0fde8d091200eb5e808caf25fe618c02f48e4efa"
@ -3486,6 +3541,13 @@ debug@^4.1.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3:
dependencies:
ms "2.1.2"
debug@^4.3.5:
version "4.3.5"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==
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"
@ -4480,7 +4542,7 @@ fast-glob@^3.2.11, fast-glob@^3.2.9:
merge2 "^1.3.0"
micromatch "^4.0.4"
fast-glob@^3.2.12:
fast-glob@^3.2.12, fast-glob@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
@ -6255,6 +6317,14 @@ loader-utils@^2.0.0:
emojis-list "^3.0.0"
json5 "^2.1.2"
local-pkg@^0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c"
integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==
dependencies:
mlly "^1.4.2"
pkg-types "^1.0.3"
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
@ -6490,6 +6560,13 @@ minimatch@^3.0.4:
dependencies:
brace-expansion "^1.1.7"
minimatch@^9.0.5:
version "9.0.5"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5"
integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==
dependencies:
brace-expansion "^2.0.1"
minimist-options@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/minimist-options/-/minimist-options-4.1.0.tgz#c0655713c53a8a2ebd77ffa247d342c40f010619"
@ -6517,6 +6594,16 @@ mkdirp@^1.0.4:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
mlly@^1.4.2, mlly@^1.7.1:
version "1.7.1"
resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.1.tgz#e0336429bb0731b6a8e887b438cbdae522c8f32f"
integrity sha512-rrVRZRELyQzrIUAVMHxP97kv+G786pHmOKzuFII8zDYahFBS7qnHh2AlYSl1GAHhaMPCz6/oHjVMcfFYgFYHgA==
dependencies:
acorn "^8.11.3"
pathe "^1.1.2"
pkg-types "^1.1.1"
ufo "^1.5.3"
mock-apollo-client@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/mock-apollo-client/-/mock-apollo-client-1.2.1.tgz#e3bfdc3ff73b1fea28fa7e91ec82e43ba8cbfa39"
@ -7025,6 +7112,11 @@ path-type@^4.0.0:
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b"
integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==
pathe@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
@ -7050,6 +7142,11 @@ picomatch@^2.2.1:
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad"
integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==
picomatch@^2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42"
integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@ -7093,6 +7190,15 @@ pkg-dir@^4.1.0, pkg-dir@^4.2.0:
dependencies:
find-up "^4.0.0"
pkg-types@^1.0.3, pkg-types@^1.1.1:
version "1.1.3"
resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.3.tgz#161bb1242b21daf7795036803f28e30222e476e3"
integrity sha512-+JrgthZG6m3ckicaOB74TwQ+tBWsFl3qVQg7mN8ulwSOElJ7gBhKzj2VkCPnZ4NlF6kEquYU+RIYNVAvzd54UA==
dependencies:
confbox "^0.1.7"
mlly "^1.7.1"
pathe "^1.1.2"
portal-vue@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/portal-vue/-/portal-vue-3.0.0.tgz#0f60fe3540e479d18f998d32d415c50c8e17c9a9"
@ -7244,6 +7350,11 @@ prop-types@^15.7.2:
object-assign "^4.1.1"
react-is "^16.13.1"
property-expr@^2.0.5:
version "2.0.6"
resolved "https://registry.yarnpkg.com/property-expr/-/property-expr-2.0.6.tgz#f77bc00d5928a6c748414ad12882e83f24aec1e8"
integrity sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==
proto-list@~1.2.1:
version "1.2.4"
resolved "https://registry.yarnpkg.com/proto-list/-/proto-list-1.2.4.tgz#212d5bfe1318306a420f6402b8e26ff39647a849"
@ -8392,6 +8503,11 @@ throttle-debounce@^5.0.0:
resolved "https://registry.yarnpkg.com/throttle-debounce/-/throttle-debounce-5.0.2.tgz#ec5549d84e053f043c9fd0f2a6dd892ff84456b1"
integrity sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==
tiny-case@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/tiny-case/-/tiny-case-1.0.3.tgz#d980d66bc72b5d5a9ca86fb7c9ffdb9c898ddd03"
integrity sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==
tmpl@1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/tmpl/-/tmpl-1.0.5.tgz#8683e0b902bb9c20c4f726e3c0b69f36518c07cc"
@ -8449,6 +8565,11 @@ toposort@^1.0.0:
resolved "https://registry.yarnpkg.com/toposort/-/toposort-1.0.7.tgz#2e68442d9f64ec720b8cc89e6443ac6caa950029"
integrity sha1-LmhELZ9k7HILjMieZEOsbKqVACk=
toposort@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/toposort/-/toposort-2.0.2.tgz#ae21768175d1559d48bef35420b2f4962f09c330"
integrity sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==
tough-cookie@^2.3.3, tough-cookie@~2.5.0:
version "2.5.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2"
@ -8590,6 +8711,11 @@ type-fest@^0.8.1:
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d"
integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==
type-fest@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b"
integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==
type-fest@^4.8.3:
version "4.21.0"
resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-4.21.0.tgz#2eec399d9bda4ac686286314d07c6675fef3fdd8"
@ -8610,6 +8736,11 @@ typedarray-to-buffer@^3.1.5:
dependencies:
is-typedarray "^1.0.0"
ufo@^1.5.3:
version "1.5.4"
resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.4.tgz#16d6949674ca0c9e0fbbae1fa20a71d7b1ded754"
integrity sha512-UsUk3byDzKd04EyoZ7U4DOlxQaD14JUKQl6/P7wiX4FNvUfm3XL246n9W5AmqwW5RSFJ27NAuM0iLscAOYUiGQ==
uglify-js@3.4.x:
version "3.4.10"
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.4.10.tgz#9ad9563d8eb3acdfb8d38597d2af1d815f6a755f"
@ -8671,6 +8802,32 @@ unpipe@1.0.0, unpipe@~1.0.0:
resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=
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"
integrity sha512-5wg7lbdg5ZcrAQNzyYK+6gcg/DG8K6rO+f5YeuvqGHs/PhpapBvpA4O/0ex/pFthE5WgRk43iWuRZEMLVsdz4Q==
dependencies:
"@antfu/utils" "^0.7.10"
"@rollup/pluginutils" "^5.1.0"
chokidar "^3.6.0"
debug "^4.3.5"
fast-glob "^3.3.2"
local-pkg "^0.5.0"
magic-string "^0.30.10"
minimatch "^9.0.5"
mlly "^1.7.1"
unplugin "^1.11.0"
unplugin@^1.11.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/unplugin/-/unplugin-1.11.0.tgz#09237b4011075e65c8f4d0ae06e221dee12750e3"
integrity sha512-3r7VWZ/webh0SGgJScpWl2/MRCZK5d3ZYFcNaeci/GQ7Teop7zf0Nl2pUuz7G21BwPd9pcUPOC5KmJ2L3WgC5g==
dependencies:
acorn "^8.11.3"
chokidar "^3.6.0"
webpack-sources "^3.2.3"
webpack-virtual-modules "^0.6.1"
unset-value@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559"
@ -8992,6 +9149,16 @@ webidl-conversions@^6.1.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-6.1.0.tgz#9111b4d7ea80acd40f5270d666621afa78b69514"
integrity sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==
webpack-sources@^3.2.3:
version "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:
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==
whatwg-encoding@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0"
@ -9154,6 +9321,16 @@ yargs@^15.4.1:
y18n "^4.0.0"
yargs-parser "^18.1.2"
yup@^1.3.2, yup@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/yup/-/yup-1.4.0.tgz#898dcd660f9fb97c41f181839d3d65c3ee15a43e"
integrity sha512-wPbgkJRCqIf+OHyiTBQoJiP5PFuAXaWiJK6AmYkzQAh5/c2K9hzSApBZG5wV9KoKSePF7sAxmNSvh/13YHkFDg==
dependencies:
property-expr "^2.0.5"
tiny-case "^1.0.3"
toposort "^2.0.2"
type-fest "^2.19.0"
zen-observable-ts@^0.8.21:
version "0.8.21"
resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-0.8.21.tgz#85d0031fbbde1eba3cd07d3ba90da241215f421d"