License system implemented
182
backend/data/licenses.json
Normal file
@@ -0,0 +1,182 @@
|
||||
[
|
||||
{
|
||||
"image": "alex-turner.jpg",
|
||||
"license": "CC BY 2.0",
|
||||
"creator": "Raph_PH",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/9/95/Alex_Turner%2C_Way_Out_West_2018.jpg"
|
||||
},
|
||||
{
|
||||
"image": "andy-nicholson.jpg",
|
||||
"license": "CC BY 2.0",
|
||||
"creator": "Lola's Big Adventure!",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/6/6c/Andy_Nicholson_%28cropped%29.jpg"
|
||||
},
|
||||
{
|
||||
"image": "anthony-kiedis.jpg",
|
||||
"license": "CC BY 2.0",
|
||||
"creator": "Hel Davies",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/c/ca/Anthony_Kiedis_2022.jpg"
|
||||
},
|
||||
{
|
||||
"image": "chris-martin.jpg",
|
||||
"license": "CC BY 2.0",
|
||||
"creator": "Raph_PH",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/6/68/ChrisMartinManch030623_%28cropped%29.jpg"
|
||||
},
|
||||
{
|
||||
"image": "chris-wolstenholme.jpg",
|
||||
"license": "CC BY-SA 4.0",
|
||||
"creator": "Markus Felix",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/e/eb/2018_Chris_Wolstenholme_%28cropped%29.jpg"
|
||||
},
|
||||
{
|
||||
"image": "flea.jpg",
|
||||
"license": "CC BY 2.0",
|
||||
"creator": "Piyush Kumar",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/8/8e/Flea_1012_%282%29.jpg"
|
||||
},
|
||||
{
|
||||
"image": "chad-smith.jpg",
|
||||
"license": "Gemeinfrei",
|
||||
"creator": "Bojosoto",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/4/42/Chadsmithclinic.jpg"
|
||||
},
|
||||
{
|
||||
"image": "john-frusciante.jpg",
|
||||
"license": "CC BY-SA 2.0",
|
||||
"creator": "Hel Davies",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/1/1f/John_Frusciante_%2852279466415%29.jpg"
|
||||
},
|
||||
{
|
||||
"image": "logo.png",
|
||||
"license": "MIT",
|
||||
"creator": "Tobias Zoghaib",
|
||||
"url": ""
|
||||
},
|
||||
{
|
||||
"image": "lanxess-arena-indoor.jpg",
|
||||
"license": "CC BY-SA 3.0",
|
||||
"creator": "Admin Kübelbeck",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/f/f3/Koelnarena_inside.jpg"
|
||||
},
|
||||
{
|
||||
"image": "lanxess-arena-outdoor.jpg",
|
||||
"license": "CC BY-SA 2.0",
|
||||
"creator": "Rolf H.",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/1/18/Lanxess_Arena_Flight_over_Cologne.jpg"
|
||||
},
|
||||
{
|
||||
"image": "red-hot-chili-peppers-1.jpg",
|
||||
"license": "CC BY-SA 4.0",
|
||||
"creator": "Kreepin Deth",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/1/14/RHCP_Live_in_London_26_June_2022.jpg"
|
||||
},
|
||||
{
|
||||
"image": "swiss-life-hall-indoor.jpg",
|
||||
"license": "CC BY-SA 3.0",
|
||||
"creator": "Bernd Schwabe in Hannover",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/8/89/2013-09-18_Besuch_14._Dalai_Lama_Tendzin_Gyatsho_in_Hannover%2C_future4children%2C_Swiss_Life_Hall%2C_%2876%29.JPG"
|
||||
},
|
||||
{
|
||||
"image": "swiss-life-hall-outdoor.jpg",
|
||||
"license": "Public Domain",
|
||||
"creator": "AxelHH",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/6/66/AWD_Hall_Seite.jpg"
|
||||
},
|
||||
{
|
||||
"image": "astra-kulturhaus-outdoor.jpg",
|
||||
"license": "CC BY 2.0",
|
||||
"creator": "Marcus Grbac",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/f/fd/Astra_Kulturhaus_Biergarten_RAW_Berlin_July_2017.jpg"
|
||||
},
|
||||
{
|
||||
"image": "thom-yorke.jpg",
|
||||
"license": "CC BY 2.0",
|
||||
"creator": "Raph_PH",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/2/25/RadioheadMontreal170718-70_%2843600493681%29_%28cropped%29.jpg"
|
||||
},
|
||||
{
|
||||
"image": "rami-jaffee.jpg",
|
||||
"license": "CC BY 2.0",
|
||||
"creator": "Raph_PH",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/f/fa/Rami_Jaffee_1.jpg"
|
||||
},
|
||||
{
|
||||
"image": "philip-selway.jpg",
|
||||
"license": "CC BY-SA 2.0",
|
||||
"creator": "Michell Zappa",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/1/1f/Phil_Selway.jpg"
|
||||
},
|
||||
{
|
||||
"image": "phil-harvey.jpg",
|
||||
"license": "CC BY-SA 3.0",
|
||||
"creator": "Hayley St. James",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/3/36/PhilHarveyNewYork17062021.png"
|
||||
},
|
||||
{
|
||||
"image": "pat-smear.jpg",
|
||||
"license": "GNU v.1.2",
|
||||
"creator": "Andrew Burns",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/6/66/Patsmear.jpg"
|
||||
},
|
||||
{
|
||||
"image": "mike-kerr.jpg",
|
||||
"license": "CC BY 4.0",
|
||||
"creator": "Dena Flows",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/8/85/017-BIME-2017-Royal-Blood-27X17-por-Dena-Flows.jpg"
|
||||
},
|
||||
{
|
||||
"image": "matthew-bellamy.jpg",
|
||||
"license": "CC BY 3.0",
|
||||
"creator": "Minerva97",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/d/d0/2009_Matthew_Bellamy_%28cropped%29.jpg"
|
||||
},
|
||||
{
|
||||
"image": "capitol-outside.jpg",
|
||||
"license": "",
|
||||
"creator": "AxelHH",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/6/6c/Hannover_Capitol_ganz.jpg"
|
||||
},
|
||||
{
|
||||
"image": "red-hot-chili-peppers-logo.png",
|
||||
"license": "",
|
||||
"creator": "Viiticus",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/3/31/Red_Hot_Chili_Peppers_logo.svg"
|
||||
},
|
||||
{
|
||||
"image": "red-hot-chili-peppers-2.jpg",
|
||||
"license": "CC BY-SA 4.0",
|
||||
"creator": "Roberto Gianardi",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/6/64/Red_Hot_Chili_Peppers_Bologna_2016.jpg"
|
||||
},
|
||||
{
|
||||
"image": "arctic-monkeys-1.jpg",
|
||||
"license": "CC BY 3.0",
|
||||
"creator": "Bill Ebbesen",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/0/04/Arctic_Monkeys_-_Orange_Stage_-_Roskilde_Festival_2014.jpg"
|
||||
},
|
||||
{
|
||||
"image": ".jpg",
|
||||
"license": "CC BY-SA 2.0",
|
||||
"creator": "",
|
||||
"url": ""
|
||||
},
|
||||
{
|
||||
"image": "arctic-monkeys-3.jpg",
|
||||
"license": "CC BY-SA 2.0",
|
||||
"creator": "Aurelien Guichard",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/f/f8/Arctic_Monkeys_%40_Shepherds_Bush_Empire.jpg"
|
||||
},
|
||||
{
|
||||
"image": "european-tour-arctic-monkeys.jpg",
|
||||
"license": "Gemeinfrei",
|
||||
"creator": "Matthew Cooper",
|
||||
"url": "https://upload.wikimedia.org/wikipedia/commons/e/e7/%22AM%22_%28Arctic_Monkeys%29.jpg"
|
||||
},
|
||||
{
|
||||
"image": ".jpg",
|
||||
"license": "CC BY-SA 2.0",
|
||||
"creator": "",
|
||||
"url": ""
|
||||
}
|
||||
]
|
||||
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 539 KiB |
|
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 953 KiB |
|
Before Width: | Height: | Size: 1.4 MiB After Width: | Height: | Size: 3.9 MiB |
|
Before Width: | Height: | Size: 155 KiB After Width: | Height: | Size: 6.0 MiB |
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 193 KiB |
|
Before Width: | Height: | Size: 426 KiB After Width: | Height: | Size: 88 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 1.5 MiB |
|
Before Width: | Height: | Size: 356 KiB After Width: | Height: | Size: 5.2 MiB |
|
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 447 KiB After Width: | Height: | Size: 2.3 MiB |
|
Before Width: | Height: | Size: 648 KiB After Width: | Height: | Size: 339 KiB |
|
Before Width: | Height: | Size: 197 KiB After Width: | Height: | Size: 111 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 276 KiB |
@@ -1,7 +1,8 @@
|
||||
import { Request, Response, NextFunction, Router } from 'express'
|
||||
import fs from "fs"
|
||||
import fs, { createReadStream } from "fs"
|
||||
import multer from "multer"
|
||||
const upload = multer({ dest: './backend/images/' })
|
||||
import licenses from "../data/licenses.json"
|
||||
|
||||
export const files = Router()
|
||||
|
||||
@@ -32,17 +33,20 @@ files.get("/:folder", async (req: Request, res: Response) => {
|
||||
let result = []
|
||||
let fileNames = fs.readdirSync("./backend/images/" + req.params.folder + "/")
|
||||
|
||||
|
||||
fileNames.forEach(file => {
|
||||
let resData = fs.readFileSync("./backend/images/" + req.params.folder + "/" + file, "utf8")
|
||||
let resData = ""
|
||||
let url = "http://localhost:3000/static/" + req.params.folder + "/" + file
|
||||
|
||||
if (file.endsWith("html") || file.endsWith("js")) {
|
||||
resData = fs.readFileSync("./backend/images/" + req.params.folder + "/" + file, "utf8")
|
||||
}
|
||||
|
||||
// todo License, Author, URL
|
||||
result.push({
|
||||
name: file,
|
||||
size: fs.statSync("./backend/images/" + req.params.folder + "/" + file).size,
|
||||
content: resData,
|
||||
url: "http://localhost:3000/static/" + req.params.folder + "/" + file,
|
||||
|
||||
url: url,
|
||||
copyright: licenses.find(data => data.image == file)
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ startDatabase()
|
||||
const path = require('path')
|
||||
app.use('/static', express.static(path.join(__dirname, 'images')))
|
||||
app.use("/exercises", exercises)
|
||||
app.use("/files", files)
|
||||
|
||||
// Add delay for more realistic response times
|
||||
app.use((req, res, next) => {
|
||||
@@ -44,7 +45,6 @@ app.use("/orders", order)
|
||||
app.use("/accounts", account)
|
||||
app.use("/cities", city)
|
||||
app.use("/concerts", concert)
|
||||
app.use("/files", files)
|
||||
|
||||
// Start server
|
||||
const server = app.listen(port, () => {
|
||||
|
||||
50
package-lock.json
generated
@@ -14,6 +14,8 @@
|
||||
"axios": "^1.7.7",
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"csv": "^6.3.11",
|
||||
"csv-reader": "^1.0.12",
|
||||
"exif-js": "^2.3.0",
|
||||
"exifreader": "^4.25.0",
|
||||
"express": "^4.21.1",
|
||||
@@ -4286,6 +4288,48 @@
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/csv": {
|
||||
"version": "6.3.11",
|
||||
"resolved": "https://registry.npmjs.org/csv/-/csv-6.3.11.tgz",
|
||||
"integrity": "sha512-a8bhT76Q546jOElHcTrkzWY7Py925mfLO/jqquseH61ThOebYwOjLbWHBqdRB4K1VpU36sTyIei6Jwj7QdEZ7g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"csv-generate": "^4.4.2",
|
||||
"csv-parse": "^5.6.0",
|
||||
"csv-stringify": "^6.5.2",
|
||||
"stream-transform": "^3.3.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.1.90"
|
||||
}
|
||||
},
|
||||
"node_modules/csv-generate": {
|
||||
"version": "4.4.2",
|
||||
"resolved": "https://registry.npmjs.org/csv-generate/-/csv-generate-4.4.2.tgz",
|
||||
"integrity": "sha512-W6nVsf+rz0J3yo9FOjeer7tmzBJKaTTxf7K0uw6GZgRocZYPVpuSWWa5/aoWWrjQZj4/oNIKTYapOM7hiNjVMA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/csv-parse": {
|
||||
"version": "5.6.0",
|
||||
"resolved": "https://registry.npmjs.org/csv-parse/-/csv-parse-5.6.0.tgz",
|
||||
"integrity": "sha512-l3nz3euub2QMg5ouu5U09Ew9Wf6/wQ8I++ch1loQ0ljmzhmfZYrH9fflS22i/PQEvsPvxCwxgz5q7UB8K1JO4Q==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/csv-reader": {
|
||||
"version": "1.0.12",
|
||||
"resolved": "https://registry.npmjs.org/csv-reader/-/csv-reader-1.0.12.tgz",
|
||||
"integrity": "sha512-0AAgazKJUywtjvZbclNuovIiQY/WyvojWw15Y2k3kPixE+pDiOFnfg5FcH3CfDqqnrB2f3p5oPAc446EXD01Tw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=8.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/csv-stringify": {
|
||||
"version": "6.5.2",
|
||||
"resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.5.2.tgz",
|
||||
"integrity": "sha512-RFPahj0sXcmUyjrObAK+DOWtMvMIFV328n4qZJhgX3x2RqkQgOTU2mCUmiFR0CzM6AzChlRSUErjiJeEt8BaQA==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/de-indent": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
|
||||
@@ -8618,6 +8662,12 @@
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/stream-transform": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/stream-transform/-/stream-transform-3.3.3.tgz",
|
||||
"integrity": "sha512-dALXrXe+uq4aO5oStdHKlfCM/b3NBdouigvxVPxCdrMRAU6oHh3KNss20VbTPQNQmjAHzZGKGe66vgwegFEIog==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/streamsearch": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||
|
||||
@@ -38,6 +38,8 @@
|
||||
"axios": "^1.7.7",
|
||||
"body-parser": "^1.20.2",
|
||||
"cors": "^2.8.5",
|
||||
"csv": "^6.3.11",
|
||||
"csv-reader": "^1.0.12",
|
||||
"exif-js": "^2.3.0",
|
||||
"exifreader": "^4.25.0",
|
||||
"express": "^4.21.1",
|
||||
|
||||
13
src/data/models/files/filesApiModel.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export class FilesApiModel {
|
||||
name: string
|
||||
size: number
|
||||
content: string
|
||||
url: string
|
||||
copyright: CopyRightModel = new CopyRightModel()
|
||||
}
|
||||
|
||||
class CopyRightModel {
|
||||
license: string = ""
|
||||
creator: string = ""
|
||||
url: string = ""
|
||||
}
|
||||
@@ -19,6 +19,7 @@ filesStore.getStaticFolders()
|
||||
:hide-add-button="true"
|
||||
>
|
||||
<v-row >
|
||||
<!-- Column folder -->
|
||||
<v-col cols="2" class="border">
|
||||
<v-list>
|
||||
<v-list-item
|
||||
@@ -27,10 +28,13 @@ filesStore.getStaticFolders()
|
||||
:value="folder"
|
||||
:title="folder.name + '/'"
|
||||
@click="filesStore.selectedFolder = folder; filesStore.getStaticFiles()"
|
||||
prepend-icon="mdi-folder"
|
||||
/>
|
||||
</v-list>
|
||||
</v-col>
|
||||
|
||||
|
||||
<!-- Column files in folder -->
|
||||
<v-col cols="4" class="border">
|
||||
<v-skeleton-loader
|
||||
:loading="filesStore.fetchInProgress"
|
||||
@@ -41,36 +45,68 @@ filesStore.getStaticFolders()
|
||||
v-for="file of filesStore.staticFiles"
|
||||
:title="file.name"
|
||||
:value="file.name"
|
||||
:subtitle="Math.round(file.size / 1024) + ' KB'"
|
||||
@click="() => { filesStore.selectedFile = file }"
|
||||
/>
|
||||
>
|
||||
<template #prepend>
|
||||
<v-icon
|
||||
:icon="file.name.endsWith('js') ? 'mdi-file' : 'mdi-image'"
|
||||
:color="file.copyright != undefined ? 'green' : 'red'"
|
||||
/>
|
||||
</template>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-skeleton-loader>
|
||||
</v-col>
|
||||
|
||||
|
||||
<!-- File detail viewer -->
|
||||
<v-col class="border">
|
||||
<v-row>
|
||||
<v-col v-if="filesStore.selectedFile != undefined">
|
||||
{{ filesStore.selectedFile.url }}
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<v-row>
|
||||
<v-col>
|
||||
<v-textarea
|
||||
v-if="filesStore.selectedFile != undefined && filesStore.selectedFile.name.endsWith('html')"
|
||||
v-if="filesStore.selectedFile != undefined && filesStore.selectedFile.name.endsWith('js')"
|
||||
:model-value="filesStore.selectedFile.content"
|
||||
variant="outlined"
|
||||
label="Content"
|
||||
height="300"
|
||||
rows="30"
|
||||
/>
|
||||
|
||||
<v-img
|
||||
v-else-if="filesStore.selectedFile != undefined"
|
||||
:src="filesStore.selectedFile.url" max-height="400"
|
||||
/>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
<!-- File details -->
|
||||
<v-row>
|
||||
<v-col v-if="filesStore.selectedFile != undefined">
|
||||
<v-list>
|
||||
<v-list-item prepend-icon="mdi-server">
|
||||
{{ filesStore.selectedFile.url }}
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item prepend-icon="mdi-package">
|
||||
{{ Math.round(filesStore.selectedFile.size / 1024) + ' KB' }}
|
||||
</v-list-item>
|
||||
|
||||
<template v-if="filesStore.selectedFile['copyright'] != undefined">
|
||||
<v-list-item prepend-icon="mdi-copyright">
|
||||
{{ filesStore.selectedFile.copyright.license }}
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item prepend-icon="mdi-account">
|
||||
{{ filesStore.selectedFile.copyright.creator }}
|
||||
</v-list-item>
|
||||
|
||||
<v-list-item prepend-icon="mdi-web">
|
||||
<a :href="filesStore.selectedFile.copyright.url" >Quelle</a>
|
||||
</v-list-item>
|
||||
</template>
|
||||
</v-list>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</admin-data-layout>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { fetchFileNames, fetchFolderNames, postFile } from "@/data/api/files.api";
|
||||
import { FilesApiModel } from "@/data/models/files/filesApiModel";
|
||||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
|
||||
@@ -7,14 +8,17 @@ export const useFilesStore = defineStore('filesStore', {
|
||||
/** Request to server sent, waiting for data response */
|
||||
fetchInProgress: ref(false),
|
||||
|
||||
/** List of all folders on the server */
|
||||
staticFolders: ref<Array<{name: string, nrOfItems: number}>>([]),
|
||||
|
||||
/** Current selected folder in file browsre */
|
||||
selectedFolder: ref<{name: string, nrOfItems: number}>(),
|
||||
|
||||
/** List of files on the server */
|
||||
staticFiles: ref<Array<{name: string, size: number, content: string, url: string}>>([]),
|
||||
staticFiles: ref<Array<FilesApiModel>>([]),
|
||||
|
||||
selectedFile: ref<{name: string, size: number, content: string, url: string}>(),
|
||||
/** Current selected file in file browser */
|
||||
selectedFile: ref<FilesApiModel>(),
|
||||
|
||||
showFileUploadDialog: ref(false),
|
||||
|
||||
@@ -24,6 +28,9 @@ export const useFilesStore = defineStore('filesStore', {
|
||||
}),
|
||||
|
||||
actions: {
|
||||
/**
|
||||
* Fetch all static folders on the server
|
||||
*/
|
||||
async getStaticFolders() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
@@ -47,6 +54,7 @@ export const useFilesStore = defineStore('filesStore', {
|
||||
})
|
||||
},
|
||||
|
||||
|
||||
async uploadFile() {
|
||||
this.fetchInProgress = true
|
||||
|
||||
|
||||