diff --git a/frontend/src/components/AuthenticatedImage.vue b/frontend/src/components/AuthenticatedImage.vue new file mode 100644 index 0000000..84e08b9 --- /dev/null +++ b/frontend/src/components/AuthenticatedImage.vue @@ -0,0 +1,55 @@ +<template> + <div> + <!--img src=""--> + data:{{ image_data }}<br> + owner:{{ owner }}<br> + src:{{ src }}<br> + servers:{{ servers }} + </div> +</template> + +<style scoped> +img { + width: 190px; + height: 107px; + object-fit: contain; +} +</style> + +<script> +import {mapActions, mapGetters} from "vuex"; + +export default { + name: "AuthenticatedImage", + props: { + src: { + type: String, + required: true + }, + owner: { + type: String, + required: true + } + }, + data() { + return { + image_data: "", + servers: [] + } + }, + computed: { + ...mapGetters(["signAuth"]) + }, + methods: { + ...mapActions(["getFriendServers"]) + }, + async mounted() { + try { + this.servers = await this.getFriendServers({username: this.owner}); + this.image_data = await this.servers.get(this.signAuth, this.src); + } catch (e) { + console.log(e); + } + } +} +</script> \ No newline at end of file diff --git a/frontend/src/neigbors.js b/frontend/src/neigbors.js index bfb0ebc..bbdfc06 100644 --- a/frontend/src/neigbors.js +++ b/frontend/src/neigbors.js @@ -1,7 +1,8 @@ class NeighborsCache { constructor() { //this._max_age = 1000 * 60 * 60; // 1 hour - this._max_age = 1000 * 60 * 5; // 5 minutes + //this._max_age = 1000 * 60 * 5; // 5 minutes + this._max_age = 1000 * 15; // 15 seconds this._cache = JSON.parse(localStorage.getItem('neighbor-cache')) || {}; } diff --git a/frontend/src/store.js b/frontend/src/store.js index c966ebc..21a752f 100644 --- a/frontend/src/store.js +++ b/frontend/src/store.js @@ -2,7 +2,7 @@ import {createStore} from 'vuex'; import router from '@/router'; import FallBackResolver from "@/dns"; import NeighborsCache from "@/neigbors"; -import {createSignAuth, createTokenAuth, createNullAuth, ServerSet, ServerSetUnion} from "@/federation"; +import {createNullAuth, createSignAuth, createTokenAuth, ServerSet, ServerSetUnion} from "@/federation"; export default createStore({ @@ -262,6 +262,10 @@ export default createStore({ state.last_load.files = Date.now() return data }, + async fetchFilesByItem({state, commit, dispatch, getters}, {id}) { + const servers = await dispatch('getHomeServers') + return await servers.get(getters.signAuth, '/api/item_files/' + id + '/') + }, async pushFile({state, dispatch, getters}, {item_id, file}) { const servers = await dispatch('getHomeServers') const data = await servers.post(getters.signAuth, '/api/item_files/' + item_id + '/', file) diff --git a/frontend/src/views/InventoryDetail.vue b/frontend/src/views/InventoryDetail.vue index 40dcd98..d971f6f 100644 --- a/frontend/src/views/InventoryDetail.vue +++ b/frontend/src/views/InventoryDetail.vue @@ -32,6 +32,19 @@ <input type="text" class="form-control" id="image" name="image" placeholder="Enter image" v-model="item.image"> </div--> + <div class="mb-3"> + <label for="image" class="form-label">Image</label> + <div> + <img v-for="file in files" :key="file.id" :alt="file.name" + :src="'https://toolshed.j3d1.de'+file.name" class="img-thumbnail border-info"> + <!-- TODO replace dirty hack with proper solution --> + </div> + <div> + <authenticated-image v-for="file in files" :key="file.id" :src="file.name" + :owner="file.owner"></authenticated-image> + </div> + + </div> </div> </div> <!-- actions --> @@ -59,14 +72,21 @@ import BaseLayout from "@/components/BaseLayout.vue"; import TagField from "@/components/TagField.vue"; import PropertyField from "@/components/PropertyField.vue"; import {mapActions, mapGetters} from "vuex"; +import AuthenticatedImage from "@/components/AuthenticatedImage.vue"; export default { name: "InventoryDetail", components: { + AuthenticatedImage, PropertyField, TagField, BaseLayout, ...BIcons }, + data() { + return { + files: [] + } + }, props: { id: { type: String, @@ -80,14 +100,26 @@ export default { } }, methods: { - ...mapActions(["fetchInventoryItems", "deleteInventoryItem"]) + ...mapActions(["fetchInventoryItems", "deleteInventoryItem", "fetchFilesByItem"]), }, async mounted() { await this.fetchInventoryItems() + console.log(this.id, typeof this.id) + const files = await this.fetchFilesByItem({id: this.id}) + this.files = files.map(file => { + return { + ...file, + owner: this.item.owner + } + }) } } </script> <style scoped> - +img { + width: 190px; + height: 107px; + object-fit: contain; +} </style> \ No newline at end of file diff --git a/frontend/vite.config.js b/frontend/vite.config.js index d62fb1e..737b7d0 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -23,7 +23,7 @@ export default defineConfig({ 'Content-Security-Policy': 'default-src \'self\';' + ' script-src \'self\' \'wasm-unsafe-eval\';' + ' style-src \'self\' \'unsafe-inline\';' - + ' img-src \'self\' data:; ' + + ' img-src \'self\' * data:; ' + ' connect-src * data:', // TODO: change * to https://* for production }, /*https: {