diff --git a/frontend/package-lock.json b/frontend/package-lock.json index d20059c..359f06a 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -13,6 +13,7 @@ "js-nacl": "^1.4.0", "moment": "^2.29.4", "vue": "^3.2.47", + "vue-multiselect": "^2.1.7", "vue-router": "^4.1.6", "vuex": "^4.1.0" }, @@ -2062,14 +2063,14 @@ "integrity": "sha512-i/I1Omf6lADjVBlwJpQifZOePV15snHny9w04+lc71+3t8PyWuLC/7clyoOSHOBNGXFe2PAGxmTiZ+Z4HWsPyw==" }, "node_modules/vite": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.1.tgz", - "integrity": "sha512-EPmfPLAI79Z/RofuMvkIS0Yr091T2ReUoXQqc5ppBX/sjFRhHKiPPF/R46cTdoci/XgeQpB23diiJxq5w30vdg==", + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", + "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", "dev": true, "dependencies": { "esbuild": "^0.17.5", - "postcss": "^8.4.21", - "rollup": "^3.20.2" + "postcss": "^8.4.23", + "rollup": "^3.21.0" }, "bin": { "vite": "bin/vite.js" @@ -2234,6 +2235,15 @@ "@vue/shared": "3.2.47" } }, + "node_modules/vue-multiselect": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/vue-multiselect/-/vue-multiselect-2.1.7.tgz", + "integrity": "sha512-KIegcN+Ntwg3cbkY/jhw2s/+XJUM0Lpi/LcKFYCS8PrZHcWBl2iKCVze7ZCnRj3w8H7/lUJ9v7rj9KQiNxApBw==", + "engines": { + "node": ">= 4.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/vue-router": { "version": "4.1.6", "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.1.6.tgz", diff --git a/frontend/package.json b/frontend/package.json index 5b4727a..29846ea 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -13,6 +13,7 @@ "js-nacl": "^1.4.0", "moment": "^2.29.4", "vue": "^3.2.47", + "vue-multiselect": "^2.1.7", "vue-router": "^4.1.6", "vuex": "^4.1.0" }, diff --git a/frontend/src/federation.js b/frontend/src/federation.js index b91b5ea..f4553bd 100644 --- a/frontend/src/federation.js +++ b/frontend/src/federation.js @@ -190,12 +190,11 @@ class ServerSetUnion { async get(auth, target) { try { - const ret = await this.serverSets.reduce(async (acc, serverset) => { + return await this.serverSets.reduce(async (acc, serverset) => { return acc.then(async (acc) => { return acc.concat(await serverset.get(auth, target)) }) }, Promise.resolve([])) - return ret } catch (e) { throw new Error('all servers failed') } @@ -203,12 +202,11 @@ class ServerSetUnion { async post(auth, target, data) { try { - const ret = await this.serverSets.reduce(async (acc, serverset) => { + return await this.serverSets.reduce(async (acc, serverset) => { return acc.then(async (acc) => { return acc.concat(await serverset.post(auth, target, data)) }) }, Promise.resolve([])) - return ret } catch (e) { throw new Error('all servers failed') } @@ -216,12 +214,11 @@ class ServerSetUnion { async patch(auth, target, data) { try { - const ret = await this.serverSets.reduce(async (acc, serverset) => { + return await this.serverSets.reduce(async (acc, serverset) => { return acc.then(async (acc) => { return acc.concat(await serverset.patch(auth, target, data)) }) }, Promise.resolve([])) - return ret } catch (e) { throw new Error('all servers failed') } @@ -229,12 +226,11 @@ class ServerSetUnion { async put(auth, target, data) { try { - const ret = await this.serverSets.reduce(async (acc, serverset) => { + return await this.serverSets.reduce(async (acc, serverset) => { return acc.then(async (acc) => { return acc.concat(await serverset.put(auth, target, data)) }) }, Promise.resolve([])) - return ret } catch (e) { throw new Error('all servers failed') } @@ -242,12 +238,11 @@ class ServerSetUnion { async delete(auth, target) { try { - const ret = await this.serverSets.reduce(async (acc, serverset) => { + return await this.serverSets.reduce(async (acc, serverset) => { return acc.then(async (acc) => { return acc.concat(await serverset.delete(auth, target)) }) }, Promise.resolve([])) - return ret } catch (e) { throw new Error('all servers failed') } diff --git a/frontend/src/store.js b/frontend/src/store.js index 0884638..df69f85 100644 --- a/frontend/src/store.js +++ b/frontend/src/store.js @@ -23,6 +23,7 @@ export default createStore({ unreachable_neighbors: new NeighborsCache(), tags: [], properties: [], + files: [], }, mutations: { setUser(state, user) { @@ -67,6 +68,9 @@ export default createStore({ setProperties(state, properties) { state.properties = properties; }, + setFiles(state, files) { + state.files = files; + }, logout(state) { state.user = null; state.token = null; @@ -236,6 +240,22 @@ export default createStore({ // TODO implement console.log('declining friend ' + args) }, + async fetchFiles({state, commit, dispatch, getters}) { + if (state.last_load.files > Date.now() - 1000 * 60 * 60 * 24) { + return state.files + } + const servers = await dispatch('getHomeServers') + const data = await servers.get(getters.signAuth, '/api/files/') + commit('setFiles', data) + state.last_load.files = Date.now() + return data + }, + async pushFile({state, dispatch, getters}, {file}) { + const servers = await dispatch('getHomeServers') + const data = await servers.post(getters.signAuth, '/api/files/', file) + state.files.push(data) + return data + }, async fetchTags({state, commit, dispatch, getters}) { if (state.last_load.tags > Date.now() - 1000 * 60 * 60 * 24) { return state.tags diff --git a/frontend/src/views/InventoryEdit.vue b/frontend/src/views/InventoryEdit.vue index cf516bb..e1ef54c 100644 --- a/frontend/src/views/InventoryEdit.vue +++ b/frontend/src/views/InventoryEdit.vue @@ -29,6 +29,10 @@ <input type="number" class="form-control" id="quantity" name="quantity" placeholder="Enter quantity" v-model="item.owned_quantity"> </div> + <div class="mb-3"> + <label for="image" class="form-label">Image</label> + <combined-file-field :value="item.files"></combined-file-field> + </div> </div> <div class="card"> <button type="submit" class="btn btn-primary" @click="updateInventoryItem(item)">Update @@ -47,6 +51,7 @@ import {mapActions, mapGetters} from "vuex"; import BaseLayout from "@/components/BaseLayout.vue"; import TagField from "@/components/TagField.vue"; import PropertyField from "@/components/PropertyField.vue"; +import CombinedFileField from "@/components/CombinedFileField.vue"; export default { name: "InventoryEdit", @@ -54,6 +59,7 @@ export default { BaseLayout, TagField, PropertyField, + CombinedFileField, ...BIcons }, props: { diff --git a/frontend/src/views/InventoryNew.vue b/frontend/src/views/InventoryNew.vue index 8c17b48..0b78fc0 100644 --- a/frontend/src/views/InventoryNew.vue +++ b/frontend/src/views/InventoryNew.vue @@ -29,12 +29,10 @@ <input type="number" class="form-control" id="quantity" name="quantity" placeholder="Enter quantity" v-model="item.owned_quantity"> </div> - <!-- TODO --> - <!--div class="mb-3"> + <div class="mb-3"> <label for="image" class="form-label">Image</label> - <input type="text" class="form-control" id="image" name="image" - placeholder="Enter image" v-model="item.image"> - </div--> + <combined-file-field :value="item.files"></combined-file-field> + </div> </div> <div class="card"> <button type="submit" class="btn btn-primary" @@ -54,6 +52,7 @@ import {mapActions} from "vuex"; import BaseLayout from "@/components/BaseLayout.vue"; import TagField from "@/components/TagField.vue"; import PropertyField from "@/components/PropertyField.vue"; +import CombinedFileField from "@/components/CombinedFileField.vue"; export default { name: "InventoryNew", @@ -61,6 +60,7 @@ export default { BaseLayout, TagField, PropertyField, + CombinedFileField, ...BIcons }, data() { diff --git a/frontend/vite.config.js b/frontend/vite.config.js index e711d7b..a2af71a 100644 --- a/frontend/vite.config.js +++ b/frontend/vite.config.js @@ -46,6 +46,9 @@ export default defineConfig({ '^/static/': { target: "http://127.0.0.1:8000/", }, + '^/media/': { + target: "http://127.0.0.1:8000/", + }, '^/wiki/': { target: "http://127.0.0.1:8080/", rewrite: (path) => path.replace(/^\/wiki/, ''),