En-/decryption fixed
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
<template>
|
||||
<nav>
|
||||
<ul>
|
||||
<li v-for="(item, key) in menu" :key="key" class="mainmenuitem">
|
||||
<a :href="item.path" v-if="item.path" class="menuitem">{{ $t(`navigation.${key}`) }}</a>
|
||||
<span v-if="!item.path" class="menuitem">{{ $t(`navigation.${key}`) }}</span>
|
||||
<li v-for="(item, key) in menu" :key="key" class="mainmenuitem" @click="openPage(item.path ?? null)">
|
||||
<span v-if="item.icon" :style="`background-image:url('/images/icons/${item.icon}')`"
|
||||
class="menu-icon"> </span>
|
||||
<span>{{ $t(`navigation.${key}`) }}</span>
|
||||
<ul v-if="item.children" class="submenu1">
|
||||
<li v-for="(subitem, subkey) in item.children" :key="subitem.text">
|
||||
<a :href="subitem.path" v-if="subitem.path">{{ $t(`navigation.m-${key}.${subkey}`) }}</a>
|
||||
<span v-if="!subitem.path">{{ $t(`navigation.m-${key}.${subkey}`) }}</span>
|
||||
<li v-for="(subitem, subkey) in item.children" :key="subitem.text" @click="openPage(subitem.path ?? null)">
|
||||
<span v-if="subitem.icon" :style="`background-image:url('/images/icons/${subitem.icon}')`" class="submenu-icon"> </span>
|
||||
<span>{{ $t(`navigation.m-${key}.${subkey}`) }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -37,6 +38,11 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
...mapActions(['loadMenu', 'logout']),
|
||||
openPage(url) {
|
||||
if (url) {
|
||||
this.$router.push(url);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
@@ -71,11 +77,12 @@ nav>ul>li:hover {
|
||||
background-color: #D37C06;
|
||||
white-space: nowrap;
|
||||
}
|
||||
nav>ul>li:hover > span {
|
||||
|
||||
nav>ul>li:hover>span {
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
nav>ul>li:hover > ul{
|
||||
nav>ul>li:hover>ul {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
@@ -119,13 +126,33 @@ a {
|
||||
left: 0;
|
||||
top: 2.5em;
|
||||
}
|
||||
.submenu1 > li {
|
||||
|
||||
.submenu1>li {
|
||||
padding: 0.5em;
|
||||
line-height: 1em;
|
||||
color: #7E471B;
|
||||
}
|
||||
|
||||
.submenu1>li:hover {
|
||||
color: #000000;
|
||||
background-color: #D37C06;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 3px;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
.submenu-icon {
|
||||
width: 1.2em;
|
||||
height: 1em;
|
||||
margin-right: 3px;
|
||||
background-repeat: no-repeat;
|
||||
display: inline-block;
|
||||
line-height: 1em;
|
||||
background-size: 1.2em 1.2em;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -13,15 +13,14 @@
|
||||
:list="getSettingOptions(setting.name, setting.options)" @input="handleInput(setting.id, $event)" />
|
||||
<InputNumberWidget v-else-if="setting.datatype == 'int'"
|
||||
:labelTr="`settings.personal.label.${setting.name}`"
|
||||
:tooltipTr="`settings.personal.tooltip.${setting.name}`" :value=setting.value min="0" max="200"
|
||||
@input="handleInput(setting.id, $event)" />
|
||||
:tooltipTr="`settings.personal.tooltip.${setting.name}`" :value="convertToInt(setting.value)" min="0"
|
||||
max="200" @input="handleInput(setting.id, $event)" />
|
||||
<FloatInputWidget v-else-if="setting.datatype == 'float'"
|
||||
:labelTr="`settings.personal.label.${setting.name}`"
|
||||
:tooltipTr="`settings.personal.tooltip.${setting.name}`" :value=setting.value
|
||||
:tooltipTr="`settings.personal.tooltip.${setting.name}`" :value="convertToFloat(setting.value)"
|
||||
@input="handleInput(setting.id, $event)" />
|
||||
<CheckboxWidget v-else-if="setting.datatype == 'bool'"
|
||||
:labelTr="`settings.personal.label.${setting.name}`"
|
||||
:tooltipTr="`settings.personal.tooltip.${setting.name}`" :value=setting.value
|
||||
<CheckboxWidget v-else-if="setting.datatype == 'bool'" :labelTr="`settings.personal.label.${setting.name}`"
|
||||
:tooltipTr="`settings.personal.tooltip.${setting.name}`" :value="convertToBool(setting.value)"
|
||||
@input="handleInput(setting.id, $event)" />
|
||||
<div v-else>{{ setting }}
|
||||
</div>
|
||||
@@ -104,6 +103,23 @@ export default {
|
||||
{ value: 'en', captionTr: 'settings.personal.languages.en' },
|
||||
{ value: 'de', captionTr: 'settings.personal.languages.de' },
|
||||
];
|
||||
},
|
||||
convertToInt(value) {
|
||||
const intValue = parseInt(value, 10);
|
||||
return isNaN(intValue) ? 0 : intValue;
|
||||
},
|
||||
convertToFloat(value) {
|
||||
const floatValue = parseFloat(value);
|
||||
return isNaN(floatValue) ? 0.0 : floatValue;
|
||||
},
|
||||
convertToBool(value) {
|
||||
if (value === 'true' || value === true) {
|
||||
return true;
|
||||
} else if (value === 'false' || value === false) {
|
||||
return false;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
||||
@@ -41,7 +41,6 @@ label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
input[type="checkbox"] {
|
||||
margin-right: 0.5em;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
formattedValue() {
|
||||
return this.value != null ? this.value.toFixed(this.decimals) : '';
|
||||
return this.value != null && typeof this.value === 'float' ? this.value.toFixed(this.decimals) : '';
|
||||
},
|
||||
step() {
|
||||
return Math.pow(10, -this.decimals);
|
||||
|
||||
@@ -16,7 +16,11 @@
|
||||
"weight": "Gewicht",
|
||||
"bodyheight": "Größe",
|
||||
"piercings": "Piercings",
|
||||
"tattoos": "Tattoos"
|
||||
"tattoos": "Tattoos",
|
||||
"sexualpreference": "Ausrichtung",
|
||||
"pubichair": "Schamhaare",
|
||||
"penislenght": "Penislänge",
|
||||
"brasize": "BH-Größe"
|
||||
},
|
||||
"tooltip": {
|
||||
"language": "Sprache",
|
||||
@@ -32,7 +36,11 @@
|
||||
"weight": "Gewicht",
|
||||
"bodyheight": "Größe",
|
||||
"piercings": "Piercings",
|
||||
"tattoos": "Tattoos"
|
||||
"tattoos": "Tattoos",
|
||||
"sexualpreference": "Ausrichtung",
|
||||
"pubichair": "Schamhaare",
|
||||
"penislenght": "Penislänge",
|
||||
"brasize": "BH-Größe"
|
||||
},
|
||||
"gender": {
|
||||
"male": "Männlich",
|
||||
@@ -83,10 +91,42 @@
|
||||
"medium": "Mittel",
|
||||
"less": "Wenige",
|
||||
"none": "Keine"
|
||||
},
|
||||
"sexualpreference": {
|
||||
"straight": "Heterosexuell",
|
||||
"gay": "Homosexuell",
|
||||
"bi": "Bisexuell",
|
||||
"asexual": "Asexuell",
|
||||
"pan": "Pansexuell"
|
||||
},
|
||||
"pubichair": {
|
||||
"none": "Keine",
|
||||
"short": "Kurz",
|
||||
"medium": "Mittel",
|
||||
"long": "Lang",
|
||||
"hairy": "Natürlich",
|
||||
"waxed": "Heißwachsentfernung",
|
||||
"landingstrip": "Landebahn",
|
||||
"bikinizone": "Nur Bikinizone",
|
||||
"other": "Andere"
|
||||
}
|
||||
},
|
||||
"view": {
|
||||
"title": "Aussehen"
|
||||
},
|
||||
"sexuality": {
|
||||
"title": "Sexualität"
|
||||
},
|
||||
"account": {
|
||||
"title": "Account",
|
||||
"username": "Benutzername",
|
||||
"email": "Email-Adresse",
|
||||
"newpassword": "Passwort",
|
||||
"newpasswordretype": "Passwort wiederholen",
|
||||
"deleteAccount": "Account löschen",
|
||||
"language": "Sprache",
|
||||
"showinsearch": "In Usersuchen anzeigen",
|
||||
"changeaction": "Benutzerdaten ändern"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import HomeView from '../views/HomeView.vue';
|
||||
import ActivateView from '../views/auth/ActivateView.vue';
|
||||
import PeronalSettingsView from '../views/settings/PersonalView.vue';
|
||||
import ViewSettingsView from '../views/settings/ViewView.vue';
|
||||
import SexualitySettingsView from '../views/settings/SexualityView.vue';
|
||||
import AccountSettingsView from '../views/settings/AccountView.vue';
|
||||
|
||||
const routes = [
|
||||
{
|
||||
@@ -28,6 +30,18 @@ const routes = [
|
||||
component: ViewSettingsView,
|
||||
meta: { requiresAuth: true }
|
||||
},
|
||||
{
|
||||
path: '/settings/sexuality',
|
||||
name: 'Sexuality settings',
|
||||
component: SexualitySettingsView,
|
||||
meta: { requiresAuth: true }
|
||||
},
|
||||
{
|
||||
path: '/settings/account',
|
||||
name: 'Account settings',
|
||||
component: AccountSettingsView,
|
||||
meta: { requiresAuth: true }
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import axios from 'axios';
|
||||
import store from '../store';
|
||||
|
||||
const apiClient = axios.create({
|
||||
baseURL: process.env.VUE_APP_API_BASE_URL || 'http://localhost:3001',
|
||||
@@ -7,4 +8,18 @@ const apiClient = axios.create({
|
||||
}
|
||||
});
|
||||
|
||||
apiClient.interceptors.request.use(config => {
|
||||
console.log('loading user');
|
||||
const user = store.getters.user;
|
||||
console.log(user);
|
||||
if (user && user.authCode) {
|
||||
console.log('set auth');
|
||||
config.headers['userId'] = user.id;
|
||||
config.headers['authCode'] = user.authCode;
|
||||
}
|
||||
return config;
|
||||
}, error => {
|
||||
return Promise.reject(error);
|
||||
});
|
||||
|
||||
export default apiClient;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import axios from 'axios';
|
||||
import apiClient from './axios';
|
||||
import store from '../store';
|
||||
|
||||
const loadMenu = async () => {
|
||||
@@ -7,7 +7,7 @@ const loadMenu = async () => {
|
||||
if (!userId) {
|
||||
throw new Error('User ID not found');
|
||||
}
|
||||
const response = await axios.get('/api/navigation/' + userId);
|
||||
const response = await apiClient.get('/api/navigation/' + userId);
|
||||
return response.data;
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
|
||||
73
frontend/src/views/settings/AccountView.vue
Normal file
73
frontend/src/views/settings/AccountView.vue
Normal file
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>{{ $t("settings.account.title") }}</h2>
|
||||
<div>
|
||||
<label><span>{{ $t("settings.account.username") }} </span><input type="text" v-model="username"
|
||||
:placeholder="$t('settings.account.username')" /></label>
|
||||
</div>
|
||||
<div>
|
||||
<label><span>{{ $t("settings.account.email") }} </span><input type="text" v-model="email"
|
||||
:placeholder="$t('settings.account.email')" /></label>
|
||||
</div>
|
||||
<div>
|
||||
<label><span>{{ $t("settings.account.newpassword") }} </span><input type="password" v-model="newpassword"
|
||||
:placeholder="$t('settings.account.newpassword')" /></label>
|
||||
</div>
|
||||
<div>
|
||||
<label><span>{{ $t("settings.account.newpasswordretype") }} </span><input type="password"
|
||||
v-model="newpasswordretype" :placeholder="$t('settings.account.newpasswordretype')" /></label>
|
||||
</div>
|
||||
<div>
|
||||
<label><span>{{ $t("settings.account.oldpassword") }} </span><input type="password"
|
||||
v-model="oldpassword" :placeholder="$t('settings.account.oldpassword')" /></label>
|
||||
</div>
|
||||
<div>
|
||||
<button @click="changeAccount">{{ $t("settings.account.changeaction") }}</button>
|
||||
</div>
|
||||
<div>
|
||||
<label><input type="checkbox" v-model="showInSearch" /> {{ $t("settings.account.showinsearch") }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import apiClient from '@/utils/axios.js';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: "AccountSettingsView",
|
||||
components: {},
|
||||
computed: {
|
||||
...mapGetters(['user']),
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
username: "",
|
||||
email: "",
|
||||
newpassword: "",
|
||||
newpasswordretype: "",
|
||||
showInSearch: false,
|
||||
oldpassword: "",
|
||||
};
|
||||
},
|
||||
methods: {},
|
||||
async mounted() {
|
||||
const response = await apiClient.post('/api/settings/account', { userId: this.user.id });
|
||||
console.log(response.data);
|
||||
this.username = response.data.username;
|
||||
this.showInSearch = response.data.showinsearch;
|
||||
this.email = response.data.email;
|
||||
console.log(this.showInSearch);
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
label > span {
|
||||
width: 15em;
|
||||
display: inline-block;
|
||||
}
|
||||
</style>
|
||||
17
frontend/src/views/settings/SexualityView.vue
Normal file
17
frontend/src/views/settings/SexualityView.vue
Normal file
@@ -0,0 +1,17 @@
|
||||
<template>
|
||||
<div>
|
||||
<h2>{{ $t("settings.sexuality.title") }}</h2>
|
||||
<SettingsWidget :settingsType="'sexuality'" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SettingsWidget from '@/components/SettingsWidget.vue';
|
||||
|
||||
export default {
|
||||
name: 'SexualitySettingsView',
|
||||
components: {
|
||||
SettingsWidget,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user