This commit is contained in:
j3d1 2026-08-01 12:17:37 +02:00
parent 32addb8ed1
commit 2f8683add1
15 changed files with 610 additions and 134 deletions

View file

@ -2,7 +2,7 @@
<badge-select-field :value="this.value" :options="this.tags" @addElement="addTag" ref="badgeSelect">
<template v-slot:default="{option, index}">
<span class="badge bg-dark" @click="removeTag(index)">
{{ option }}
{{ getNameFromHandle(option) }}
</span>
</template>
</badge-select-field>
@ -20,7 +20,7 @@
<script>
import * as BIcons from "bootstrap-icons-vue";
import {mapActions, mapState} from "vuex";
import {mapActions, mapState, mapGetters} from "vuex";
//import BadgeSelectField from "@/../extras/components/inputs/BadgeSelectField.vue";
import BadgeSelectField from "@/components/inputs/BadgeSelectField.vue";
@ -42,6 +42,7 @@ export default {
},
computed: {
...mapState(["tags"]),
...mapGetters(["getNameFromHandle"]),
availableTags() {
return this.tags.filter(tag => !this.localValue.includes(tag));
},

View file

@ -678,5 +678,17 @@ export default createStore({
}
return fallbackDefault
},
/**
* Extracts the human-readable name from a fully qualified handle.
* Handles look like "git:tools#tag:drill" or "git:base#property:length".
* If the given value does not look like a handle, it is returned unchanged.
*/
getNameFromHandle: () => (handle) => {
if (typeof handle !== 'string') {
return handle;
}
const match = handle.match(/#(?:tag|property):(.+)$/);
return match ? match[1] : handle;
},
}
})

View file

@ -13,7 +13,7 @@
<div class="mb-3">
<label for="tags" class="form-label">Tags</label>
<span class="badge bg-dark" v-for="(tag, index) in item.tags" :key="index">
{{ tag }}
{{ getNameFromHandle(tag) }}
</span>
</div>
<div class="mb-3">
@ -74,7 +74,7 @@ export default {
}
},
computed: {
...mapGetters(["loaded_items"]),
...mapGetters(["loaded_items", "getNameFromHandle"]),
...mapState(["storage_locations"]),
item() {
return this.loaded_items.find(item => item.id === parseInt(this.id)) || {}

View file

@ -51,14 +51,35 @@
<script>
import BaseLayout from "@/components/BaseLayout.vue";
import {mapActions, mapGetters, mapMutations} from "vuex";
export default {
name: 'Settings',
components: {BaseLayout},
computed: {
...mapGetters(['signAuth'])
},
methods: {
deleteAccount() {
if (confirm('Are you sure you want to delete your account?')) {
alert('Account deleted');
...mapActions(['getHomeServers']),
...mapMutations(['logout']),
async deleteAccount() {
if (!confirm('Are you sure you want to permanently delete your account? ' +
'All your data will be deleted and you will not be able to log back in. This cannot be undone.')) {
return;
}
try {
const servers = await this.getHomeServers();
const response = await servers.delete(this.signAuth, '/api/account/');
if (!response || !response.ok) {
const errorBody = response ? await response.json().catch(() => ({})) : {};
alert('Account deletion failed: ' + (errorBody.detail || response?.statusText || 'unknown error'));
return;
}
alert('Your account has been permanently deleted.');
this.logout();
} catch (error) {
console.error('Account deletion failed', error);
alert('Account deletion failed: ' + error);
}
},
}

View file

@ -72,7 +72,7 @@
</template>
<script>
import {mapActions, mapGetters, mapMutations} from 'vuex';
import {mapActions, mapGetters} from 'vuex';
import router from "@/router";
//import VueQrcode from '@chenfengyuan/vue-qrcode';
@ -95,9 +95,29 @@ export default {
this.selectedFile = file;
}
},
deleteData() {
if (confirm('Are you sure you want to delete your data?')) {
alert('Data deleted');
async deleteData() {
if (!confirm('Are you sure you want to permanently delete all your data (inventory, locations, ' +
'settings, friends and files)? Your account itself will stay - this cannot be undone.')) {
return;
}
try {
const servers = await this.getHomeServers();
const response = await servers.delete(this.signAuth, '/api/account_data/');
if (!response || !response.ok) {
const errorBody = response ? await response.json().catch(() => ({})) : {};
alert('Data deletion failed: ' + (errorBody.detail || response?.statusText || 'unknown error'));
return;
}
const summary = await response.json().catch(() => ({}));
alert('All your data has been deleted: ' +
`${summary.inventory_items || 0} inventory items, ` +
`${summary.locations || 0} locations, ` +
`${summary.settings || 0} settings, ` +
`${summary.friends || 0} friends, ` +
`${summary.files || 0} files.`);
} catch (error) {
console.error('Data deletion failed', error);
alert('Data deletion failed: ' + error);
}
},
exportKey() {