toolshed/frontend/src/views/StorageLocationDetail.vue
2026-09-04 14:41:26 +02:00

122 lines
4.8 KiB
Vue

<template>
<BaseLayout>
<main class="content">
<div class="row">
<div class="col">
<div class="card">
<div class="card-header">{{ location.name }}</div>
<div class="card-body">
<div class="mb-3">
<label for="path" class="form-label">Path</label>
<div>{{ location.path }}</div>
</div>
<div class="mb-3">
<label for="description" class="form-label">Description</label>
<div>{{ location.description || '-' }}</div>
</div>
<div class="mb-3">
<label for="category" class="form-label">Category</label>
<div>
<span class="badge bg-info text-white" v-if="location.category">{{ location.category }}</span>
<span class="text-muted" v-else>-</span>
</div>
</div>
<div class="mb-3">
<label for="owner" class="form-label">Owner</label>
<div>{{ location.owner || location.owner_group || '-' }}</div>
</div>
<div class="mb-3">
<label for="visibility_policy" class="form-label">Visibility Policy</label>
<div>
<span class="badge bg-secondary text-white">{{ location.visibility_policy }}</span>
</div>
</div>
</div>
</div>
<div class="card" v-if="canEdit">
<button class="btn btn-primary" @click="$router.push({name: 'locations-edit', params: {handle, id}})">
<b-icon-pencil-square></b-icon-pencil-square>
Edit
</button>
<button type="submit" class="btn btn-danger"
@click="deleteStorageLocation(location).then(() => $router.push(ownerLocationOverviewRoute(location)))">
<b-icon-trash></b-icon-trash>
Delete
</button>
<button class="btn btn-secondary"
@click="$router.push({name: 'print', query: {kind: 'storage-location', userHandle: decodedHandle, id: id}})">
<b-icon-printer></b-icon-printer>
Print label
</button>
</div>
</div>
</div>
</main>
</BaseLayout>
</template>
<script>
import * as BIcons from "bootstrap-icons-vue";
import BaseLayout from "@/components/BaseLayout.vue";
import {mapActions, mapGetters, mapState} from "vuex";
import {decodeHandleFromUrl, ownerLocationOverviewRoute} from "@/router";
export default {
name: "StorageLocationDetail",
components: {
BaseLayout,
...BIcons
},
props: {
handle: {
type: String,
required: true
},
id: {
type: String,
required: true
}
},
data() {
return {
location: {}
}
},
computed: {
...mapGetters(["groupIdByHandle"]),
...mapState(["user", "groupMemberships"]),
decodedHandle() {
return decodeHandleFromUrl(this.handle)
},
// Am I a member of this group, hosted here or elsewhere - see InventoryDetail.vue's
// isGroupMember for the same check on the item side.
isGroupMember() {
return this.decodedHandle in this.groupIdByHandle
|| this.groupMemberships.some(m => m.handle === this.decodedHandle)
},
canEdit() {
return this.decodedHandle === this.user || this.isGroupMember
}
},
methods: {
ownerLocationOverviewRoute,
...mapActions(["fetchStorageLocationByHandle", "deleteStorageLocation", "fetchGroupMemberships"]),
async loadLocation() {
this.location = await this.fetchStorageLocationByHandle({handle: this.decodedHandle, id: this.id}) || {}
}
},
watch: {
handle: 'loadLocation',
id: 'loadLocation'
},
mounted() {
this.loadLocation()
if (this.decodedHandle.startsWith('#')) {
this.fetchGroupMemberships()
}
}
}
</script>
<style scoped>
</style>