Änderungen: - Implementierung von neuen Methoden `getAccountSettings` und `setAccountSettings` im `SettingsService`, um Benutzerkontoeinstellungen zu verwalten. - Anpassung der E-Mail-Verschlüsselung im `User`-Modell zur Verwendung von Buffer für die Speicherung und zur Verbesserung der Fehlerbehandlung bei der Entschlüsselung. - Hinzufügung eines neuen `immutable`-Feldes im `UserParamType`-Modell, um unveränderliche Einstellungen zu kennzeichnen. - Anpassungen in den Frontend-Komponenten zur Berücksichtigung von unveränderlichen Feldern und zur Verbesserung der Benutzeroberfläche. Diese Anpassungen verbessern die Sicherheit der Benutzerdaten und erweitern die Funktionalität der Kontoeinstellungen.
146 lines
4.3 KiB
Vue
146 lines
4.3 KiB
Vue
<template>
|
||
<label>
|
||
<span :style="{ width: width + 'em' }">{{ $t(labelTr) }}</span>
|
||
<Multiselect
|
||
v-model="selectedOptions"
|
||
:options="validList"
|
||
:multiple="true"
|
||
:close-on-select="false"
|
||
:clear-on-select="false"
|
||
:preserve-search="true"
|
||
:placeholder="$t('select_option')"
|
||
:track-by="'value'"
|
||
:disabled="disabled"
|
||
>
|
||
<template #option="{ option }">
|
||
<span v-if="option && option.value">{{ getTranslation(option) }}</span>
|
||
</template>
|
||
<template #tag="{ option, remove }">
|
||
<span v-if="option && option.captionTr" class="multiselect__tag">
|
||
{{ $t(option.captionTr) }}
|
||
<span @click="remove(option)">×</span>
|
||
</span>
|
||
<span v-else>@e</span>
|
||
</template>
|
||
</Multiselect>
|
||
</label>
|
||
</template>
|
||
|
||
<script>
|
||
import Multiselect from 'vue-multiselect';
|
||
import 'vue-multiselect/dist/vue-multiselect.min.css';
|
||
|
||
export default {
|
||
name: "MultiselectWidget",
|
||
components: { Multiselect },
|
||
props: {
|
||
labelTr: { type: String, required: true },
|
||
value: { type: String, required: false, default: '[]' },
|
||
tooltipTr: { type: String, required: true },
|
||
width: { type: Number, required: false, default: 10 },
|
||
list: {
|
||
type: Array,
|
||
required: true,
|
||
default: () => [] // Standardwert hinzufügen, um undefined zu vermeiden
|
||
},
|
||
disabled: {
|
||
type: Boolean,
|
||
required: false,
|
||
default: false
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
internalValues: this.stringToArray(this.value), // Speichert nur die IDs (Werte)
|
||
selectedOptions: this.getOptionsFromIds(this.stringToArray(this.value)) // Hilfsvariable, speichert die vollständigen Objekte
|
||
};
|
||
},
|
||
computed: {
|
||
validList() {
|
||
return this.validatedList(); // Immer ein Array zurückgeben
|
||
}
|
||
},
|
||
watch: {
|
||
value(newValue) {
|
||
const ids = this.stringToArray(newValue);
|
||
this.internalValues = ids; // Nur die IDs speichern
|
||
this.selectedOptions = this.getOptionsFromIds(ids); // Optionen basierend auf IDs setzen
|
||
},
|
||
selectedOptions(newOptions) {
|
||
this.internalValues = newOptions.map(option => option.value); // Nur die IDs extrahieren
|
||
this.updateValue();
|
||
}
|
||
},
|
||
methods: {
|
||
stringToArray(str) {
|
||
try {
|
||
const array = JSON.parse(str);
|
||
return array.filter(item => item !== null && item !== undefined);
|
||
} catch (error) {
|
||
console.error('Invalid JSON string in value:', str);
|
||
return [];
|
||
}
|
||
},
|
||
updateValue() {
|
||
const stringValue = JSON.stringify(this.internalValues); // In JSON-String umwandeln
|
||
this.$emit("input", stringValue); // String an das Parent-Element übermitteln
|
||
},
|
||
getTranslation(option) {
|
||
return option.captionTr ? this.$t(option.captionTr) : option.caption;
|
||
},
|
||
findOption(optionId) {
|
||
return this.validatedList().find(opt => opt.value === optionId);
|
||
},
|
||
getOptionsFromIds(ids) {
|
||
return ids.map(id => this.findOption(id)).filter(option => option); // Vollständige Objekte basierend auf IDs abrufen
|
||
},
|
||
validatedList() {
|
||
// Überprüfen, ob die Liste valide ist
|
||
if (!this.list || !Array.isArray(this.list)) {
|
||
return [];
|
||
}
|
||
return this.list.filter(option => option && option.value !== null && option.value !== undefined && (option.captionTr || option.caption));
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
label {
|
||
display: block;
|
||
margin-bottom: 1em;
|
||
}
|
||
|
||
label>span {
|
||
display: inline-block;
|
||
margin-bottom: 0.5em;
|
||
}
|
||
|
||
.multiselect {
|
||
margin-left: 0.5em;
|
||
}
|
||
|
||
.custom-tag {
|
||
background-color: #f0f0f0;
|
||
border: 1px solid #ccc;
|
||
padding: 5px;
|
||
border-radius: 4px;
|
||
margin-right: 5px;
|
||
display: inline-block;
|
||
}
|
||
|
||
.custom-tag span {
|
||
margin-left: 8px;
|
||
cursor: pointer;
|
||
}
|
||
|
||
.multiselect {
|
||
display: inline-block;
|
||
width: 7em;
|
||
}
|
||
|
||
.multiselect__tags {
|
||
white-space: nowrap;
|
||
}
|
||
</style>
|