Merge remote-tracking branch 'kloon15/vue3' into vue3

This commit is contained in:
Joep 2023-09-08 21:33:19 +02:00
commit ee619adda3
13 changed files with 388 additions and 334 deletions

View File

@ -8,7 +8,6 @@
"name": "filebrowser-frontend",
"version": "2.0.0",
"dependencies": {
"@vue/compat": "^3.3.4",
"@vueuse/core": "^10.4.1",
"ace-builds": "^1.24.1",
"clipboard": "^2.0.11",
@ -21,7 +20,6 @@
"material-icons": "^1.13.10",
"moment": "^2.29.4",
"normalize.css": "^8.0.1",
"noty": "^3.2.0-beta",
"pinia": "^2.1.6",
"pretty-bytes": "^6.1.1",
"qrcode.vue": "^3.4.1",
@ -31,11 +29,10 @@
"vue-i18n": "^9.2.2",
"vue-lazyload": "^3.0.0",
"vue-router": "^4.2.4",
"vue-simple-progress": "^1.1.1"
"vue-toastification": "^2.0.0-rc.5"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^0.12.3",
"@types/node": "^20.5.9",
"@vitejs/plugin-legacy": "^4.1.1",
"@vitejs/plugin-vue": "^4.3.3",
"@vue/eslint-config-prettier": "^8.0.0",
@ -47,11 +44,9 @@
"postcss": "^8.4.28",
"prettier": "^3.0.2",
"terser": "^5.19.2",
"typescript": "^5.2.2",
"vite": "^4.4.9",
"vite-plugin-compression2": "^0.10.4",
"vite-plugin-rewrite-all": "^1.0.1",
"vue-tsc": "^1.8.10"
"vite-plugin-rewrite-all": "^1.0.1"
}
},
"node_modules/@aashutoshrathi/word-wrap": {
@ -2493,12 +2488,6 @@
"integrity": "sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==",
"dev": true
},
"node_modules/@types/node": {
"version": "20.5.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz",
"integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ==",
"dev": true
},
"node_modules/@types/web-bluetooth": {
"version": "0.0.17",
"resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.17.tgz",
@ -2542,46 +2531,6 @@
"vue": "^3.2.25"
}
},
"node_modules/@volar/language-core": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-1.10.1.tgz",
"integrity": "sha512-JnsM1mIPdfGPxmoOcK1c7HYAsL6YOv0TCJ4aW3AXPZN/Jb4R77epDyMZIVudSGjWMbvv/JfUa+rQ+dGKTmgwBA==",
"dev": true,
"dependencies": {
"@volar/source-map": "1.10.1"
}
},
"node_modules/@volar/source-map": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-1.10.1.tgz",
"integrity": "sha512-3/S6KQbqa7pGC8CxPrg69qHLpOvkiPHGJtWPkI/1AXCsktkJ6gIk/5z4hyuMp8Anvs6eS/Kvp/GZa3ut3votKA==",
"dev": true,
"dependencies": {
"muggle-string": "^0.3.1"
}
},
"node_modules/@volar/typescript": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-1.10.1.tgz",
"integrity": "sha512-+iiO9yUSRHIYjlteT+QcdRq8b44qH19/eiUZtjNtuh6D9ailYM7DVR0zO2sEgJlvCaunw/CF9Ov2KooQBpR4VQ==",
"dev": true,
"dependencies": {
"@volar/language-core": "1.10.1"
}
},
"node_modules/@vue/compat": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compat/-/compat-3.3.4.tgz",
"integrity": "sha512-VwAsPqUqRJVxeLQPUC03Sa5d+T8UG2Qv4VItq74KmNvtQlRXICpa/sqq12BcyBB4Tz1U5paOEZxWCUoXkrZ9QQ==",
"dependencies": {
"@babel/parser": "^7.21.3",
"estree-walker": "^2.0.2",
"source-map-js": "^1.0.2"
},
"peerDependencies": {
"vue": "3.3.4"
}
},
"node_modules/@vue/compiler-core": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.4.tgz",
@ -2647,54 +2596,6 @@
"prettier": ">= 3.0.0"
}
},
"node_modules/@vue/language-core": {
"version": "1.8.10",
"resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-1.8.10.tgz",
"integrity": "sha512-db8PtM4ZZr7SYNH30XpKxUYnUBYaTvcuJ4c2whKK04fuAjbtjAIZ2al5GzGEfUlesmvkpgdbiSviRXUxgD9Omw==",
"dev": true,
"dependencies": {
"@volar/language-core": "~1.10.0",
"@volar/source-map": "~1.10.0",
"@vue/compiler-dom": "^3.3.0",
"@vue/reactivity": "^3.3.0",
"@vue/shared": "^3.3.0",
"minimatch": "^9.0.0",
"muggle-string": "^0.3.1",
"vue-template-compiler": "^2.7.14"
},
"peerDependencies": {
"typescript": "*"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@vue/language-core/node_modules/brace-expansion": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
"integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/@vue/language-core/node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@vue/reactivity": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
@ -2751,16 +2652,6 @@
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
},
"node_modules/@vue/typescript": {
"version": "1.8.10",
"resolved": "https://registry.npmjs.org/@vue/typescript/-/typescript-1.8.10.tgz",
"integrity": "sha512-vPSpTXMk4chYwvyTGjM891cKgnx2r6vtbdANOp2mRU31f4HYGyLrZBlGgiua7SaO2cLjUg8y91OipJe0t8OFhA==",
"dev": true,
"dependencies": {
"@volar/typescript": "~1.10.0",
"@vue/language-core": "1.8.10"
}
},
"node_modules/@vueuse/core": {
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.4.1.tgz",
@ -3387,12 +3278,6 @@
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
"integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA=="
},
"node_modules/de-indent": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/de-indent/-/de-indent-1.0.2.tgz",
"integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
"dev": true
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -4286,15 +4171,6 @@
"node": ">=4"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true,
"bin": {
"he": "bin/he"
}
},
"node_modules/html-encoding-sniffer": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
@ -4959,12 +4835,6 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
"dev": true
},
"node_modules/muggle-string": {
"version": "0.3.1",
"resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.3.1.tgz",
"integrity": "sha512-ckmWDJjphvd/FvZawgygcUeQCxzvohjFO5RxTjj4eq8kw359gFF3E1brjfI+viLMxss5JrHTDRHZvu2/tuy0Qg==",
"dev": true
},
"node_modules/nanoid": {
"version": "3.3.6",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
@ -5017,12 +4887,6 @@
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
"integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg=="
},
"node_modules/noty": {
"version": "3.2.0-beta-deprecated",
"resolved": "https://registry.npmjs.org/noty/-/noty-3.2.0-beta-deprecated.tgz",
"integrity": "sha512-ntRbHuQ9SnnnVFZm/oq5L1DBCaHQUvsU24AwZH3PGjAWx2YqR/IhOadMk11vmJovYiQo00oqTj6Hp+D6PGtmLA==",
"deprecated": "no longer supported"
},
"node_modules/npm-run-path": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
@ -6066,19 +5930,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/typescript": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz",
"integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==",
"devOptional": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/ufo": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.3.0.tgz",
@ -6423,71 +6274,14 @@
"vue": "^3.2.0"
}
},
"node_modules/vue-simple-progress": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/vue-simple-progress/-/vue-simple-progress-1.1.1.tgz",
"integrity": "sha512-ltLWYBA5eVQHWyt1NwZeGeK0VQC69JVh1oqUdro0po7r8Hc8SEMEyEfuwyCO4s27h5I3jbD99BKKkyPSQZgoZA=="
},
"node_modules/vue-template-compiler": {
"version": "2.7.14",
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.14.tgz",
"integrity": "sha512-zyA5Y3ArvVG0NacJDkkzJuPQDF8RFeRlzV2vLeSnhSpieO6LK2OVbdLPi5MPPs09Ii+gMO8nY4S3iKQxBxDmWQ==",
"dev": true,
"dependencies": {
"de-indent": "^1.0.2",
"he": "^1.2.0"
}
},
"node_modules/vue-tsc": {
"version": "1.8.10",
"resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-1.8.10.tgz",
"integrity": "sha512-ptpTFFDoHQgkWJF7i5iERxooiQzOGtG1uKTfmAUuS3qPuSQGq+Ky/S8BFHhnFGwoOxq/PjmGN2QSZEfg1rtzQA==",
"dev": true,
"dependencies": {
"@vue/language-core": "1.8.10",
"@vue/typescript": "1.8.10",
"semver": "^7.3.8"
},
"bin": {
"vue-tsc": "bin/vue-tsc.js"
},
"node_modules/vue-toastification": {
"version": "2.0.0-rc.5",
"resolved": "https://registry.npmjs.org/vue-toastification/-/vue-toastification-2.0.0-rc.5.tgz",
"integrity": "sha512-q73e5jy6gucEO/U+P48hqX+/qyXDozAGmaGgLFm5tXX4wJBcVsnGp4e/iJqlm9xzHETYOilUuwOUje2Qg1JdwA==",
"peerDependencies": {
"typescript": "*"
"vue": "^3.0.2"
}
},
"node_modules/vue-tsc/node_modules/lru-cache": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
"dependencies": {
"yallist": "^4.0.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/vue-tsc/node_modules/semver": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
"integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==",
"dev": true,
"dependencies": {
"lru-cache": "^6.0.0"
},
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/vue-tsc/node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/w3c-xmlserializer": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",

View File

@ -6,7 +6,7 @@
"scripts": {
"dev": "vite dev",
"serve": "vite serve",
"build": "vue-tsc -p ./tsconfig.json --noEmit && vite build --emptyOutDir",
"build": "vite build",
"watch": "vite build --watch",
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
"lint": "eslint --ext .vue,.js src/",
@ -14,7 +14,6 @@
"format": "prettier --write ."
},
"dependencies": {
"@vue/compat": "^3.3.4",
"@vueuse/core": "^10.4.1",
"ace-builds": "^1.24.1",
"clipboard": "^2.0.11",
@ -27,7 +26,6 @@
"material-icons": "^1.13.10",
"moment": "^2.29.4",
"normalize.css": "^8.0.1",
"noty": "^3.2.0-beta",
"pinia": "^2.1.6",
"pretty-bytes": "^6.1.1",
"qrcode.vue": "^3.4.1",
@ -37,11 +35,10 @@
"vue-i18n": "^9.2.2",
"vue-lazyload": "^3.0.0",
"vue-router": "^4.2.4",
"vue-simple-progress": "^1.1.1"
"vue-toastification": "^2.0.0-rc.5"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^0.12.3",
"@types/node": "^20.5.9",
"@vitejs/plugin-legacy": "^4.1.1",
"@vitejs/plugin-vue": "^4.3.3",
"@vue/eslint-config-prettier": "^8.0.0",
@ -53,15 +50,8 @@
"postcss": "^8.4.28",
"prettier": "^3.0.2",
"terser": "^5.19.2",
"typescript": "^5.2.2",
"vite": "^4.4.9",
"vite-plugin-compression2": "^0.10.4",
"vite-plugin-rewrite-all": "^1.0.1",
"vue-tsc": "^1.8.10"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie < 11"
]
"vite-plugin-rewrite-all": "^1.0.1"
}
}

View File

@ -0,0 +1,41 @@
<template>
<div class="t-container">
<span>{{ message }}</span>
<button v-if="isReport" class="action" @click.stop="clicked">
{{ reportText }}
</button>
</div>
</template>
<script>
export default {
name: "error-toast",
props: ["message", "reportText", "isReport"],
methods: {
clicked() {
window.open(
"https://github.com/filebrowser/filebrowser/issues/new/choose"
);
},
},
};
</script>
<style scoped>
.t-container {
width: 100%;
padding: 5px 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.action {
text-align: center;
height: 40px;
padding: 0 10px;
border-radius: 5px;
color: white;
cursor: pointer;
border: thin solid currentColor;
}
</style>

View File

@ -0,0 +1,223 @@
<!-- This component taken directly from vue-simple-progress
since it didnt support Vue 3 but the component itself does
https://raw.githubusercontent.com/dzwillia/vue-simple-progress/master/src/components/Progress.vue -->
<template>
<div>
<div
class="vue-simple-progress-text"
:style="text_style"
v-if="text.length > 0 && textPosition == 'top'"
>
{{ text }}
</div>
<div class="vue-simple-progress" :style="progress_style">
<div
class="vue-simple-progress-text"
:style="text_style"
v-if="text.length > 0 && textPosition == 'middle'"
>
{{ text }}
</div>
<div
style="position: relative; left: -9999px"
:style="text_style"
v-if="text.length > 0 && textPosition == 'inside'"
>
{{ text }}
</div>
<div class="vue-simple-progress-bar" :style="bar_style">
<div
:style="text_style"
v-if="text.length > 0 && textPosition == 'inside'"
>
{{ text }}
</div>
</div>
</div>
<div
class="vue-simple-progress-text"
:style="text_style"
v-if="text.length > 0 && textPosition == 'bottom'"
>
{{ text }}
</div>
</div>
</template>
<script>
var isNumber = function (n) {
return !isNaN(parseFloat(n)) && isFinite(n);
};
export default {
name: "progress-bar",
props: {
val: {
default: 0,
},
max: {
default: 100,
},
size: {
// either a number (pixel width/height) or 'tiny', 'small',
// 'medium', 'large', 'huge', 'massive' for common sizes
default: 3,
},
"bg-color": {
type: String,
default: "#eee",
},
"bar-color": {
type: String,
default: "#2196f3", // match .blue color to Material Design's 'Blue 500' color
},
"bar-transition": {
type: String,
default: "all 0.5s ease",
},
"bar-border-radius": {
type: Number,
default: 0,
},
spacing: {
type: Number,
default: 4,
},
text: {
type: String,
default: "",
},
"text-align": {
type: String,
default: "center", // 'left', 'right'
},
"text-position": {
type: String,
default: "bottom", // 'bottom', 'top', 'middle', 'inside'
},
"font-size": {
type: Number,
default: 13,
},
"text-fg-color": {
type: String,
default: "#222",
},
},
computed: {
pct() {
var pct = (this.val / this.max) * 100;
pct = pct.toFixed(2);
return Math.min(pct, this.max);
},
size_px() {
switch (this.size) {
case "tiny":
return 2;
case "small":
return 4;
case "medium":
return 8;
case "large":
return 12;
case "big":
return 16;
case "huge":
return 32;
case "massive":
return 64;
}
return isNumber(this.size) ? this.size : 32;
},
text_padding() {
switch (this.size) {
case "tiny":
case "small":
case "medium":
case "large":
case "big":
case "huge":
case "massive":
return Math.min(Math.max(Math.ceil(this.size_px / 8), 3), 12);
}
return isNumber(this.spacing) ? this.spacing : 4;
},
text_font_size() {
switch (this.size) {
case "tiny":
case "small":
case "medium":
case "large":
case "big":
case "huge":
case "massive":
return Math.min(Math.max(Math.ceil(this.size_px * 1.4), 11), 32);
}
return isNumber(this.fontSize) ? this.fontSize : 13;
},
progress_style() {
var style = {
background: this.bgColor,
};
if (this.textPosition == "middle" || this.textPosition == "inside") {
style["position"] = "relative";
style["min-height"] = this.size_px + "px";
style["z-index"] = "-2";
}
if (this.barBorderRadius > 0) {
style["border-radius"] = this.barBorderRadius + "px";
}
return style;
},
bar_style() {
var style = {
background: this.barColor,
width: this.pct + "%",
height: this.size_px + "px",
transition: this.barTransition,
};
if (this.barBorderRadius > 0) {
style["border-radius"] = this.barBorderRadius + "px";
}
if (this.textPosition == "middle" || this.textPosition == "inside") {
style["position"] = "absolute";
style["top"] = "0";
style["height"] = "100%";
(style["min-height"] = this.size_px + "px"), (style["z-index"] = "-1");
}
return style;
},
text_style() {
var style = {
color: this.textFgColor,
"font-size": this.text_font_size + "px",
"text-align": this.textAlign,
};
if (
this.textPosition == "top" ||
this.textPosition == "middle" ||
this.textPosition == "inside"
)
style["padding-bottom"] = this.text_padding + "px";
if (
this.textPosition == "bottom" ||
this.textPosition == "middle" ||
this.textPosition == "inside"
)
style["padding-top"] = this.text_padding + "px";
return style;
},
},
};
</script>

View File

@ -82,9 +82,7 @@
<div
class="credits"
v-if="
$router.currentRoute.path?.includes('/files/') && !disableUsedPercentage
"
v-if="isFiles && !disableUsedPercentage"
style="width: 90%; margin: 2em 2.5em 3em 2.5em"
>
<progress-bar :val="usage.usedPercentage" size="small"></progress-bar>
@ -112,8 +110,10 @@
</template>
<script>
import { reactive } from "vue";
import { mapActions, mapState } from "pinia";
import { useAuthStore } from "@/stores/auth";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
import * as auth from "@/utils/auth";
@ -126,17 +126,24 @@ import {
loginPage,
} from "@/utils/constants";
import { files as api } from "@/api";
import ProgressBar from "vue-simple-progress";
import ProgressBar from "@/components/ProgressBar.vue";
import prettyBytes from "pretty-bytes";
const USAGE_DEFAULT = { used: "0 B", total: "0 B", usedPercentage: 0 };
export default {
name: "sidebar",
setup() {
const usage = reactive(USAGE_DEFAULT);
return { usage };
},
components: {
ProgressBar,
},
inject: ["$showError"],
computed: {
...mapState(useAuthStore, ["user", "isLoggedIn"]),
...mapState(useFileStore, ["isFiles", "reload"]),
...mapState(useLayoutStore, ["show"]),
active() {
return this.show === "sidebar";
@ -147,36 +154,28 @@ export default {
disableUsedPercentage: () => disableUsedPercentage,
canLogout: () => !noAuth && loginPage,
},
asyncComputed: {
usage: {
async get() {
let path = this.$route.path.endsWith("/")
? this.$route.path
: this.$route.path + "/";
let usageStats = { used: 0, total: 0, usedPercentage: 0 };
if (this.disableUsedPercentage) {
return usageStats;
}
try {
let usage = await api.usage(path);
usageStats = {
used: prettyBytes(usage.used, { binary: true }),
total: prettyBytes(usage.total, { binary: true }),
usedPercentage: Math.round((usage.used / usage.total) * 100),
};
} catch (error) {
this.$showError(error);
}
return usageStats;
},
default: { used: "0 B", total: "0 B", usedPercentage: 0 },
shouldUpdate() {
return this.$router.currentRoute.path.includes("/files/");
},
},
},
methods: {
...mapActions(useLayoutStore, ["closeHovers", "showHover"]),
async fetchUsage() {
let path = this.$route.path.endsWith("/")
? this.$route.path
: this.$route.path + "/";
let usageStats = USAGE_DEFAULT;
if (this.disableUsedPercentage) {
return Object.assign(this.usage, usageStats);
}
try {
let usage = await api.usage(path);
usageStats = {
used: prettyBytes(usage.used, { binary: true }),
total: prettyBytes(usage.total, { binary: true }),
usedPercentage: Math.round((usage.used / usage.total) * 100),
};
} catch (error) {
this.$showError(error);
}
return Object.assign(this.usage, usageStats);
},
toRoot() {
this.$router.push({ path: "/files" });
this.closeHovers();
@ -190,5 +189,10 @@ export default {
},
logout: auth.logout,
},
watch: {
isFiles(newValue) {
newValue && this.fetchUsage();
},
},
};
</script>

View File

@ -48,9 +48,6 @@ import * as upload from "@/utils/upload";
export default {
name: "item",
compatConfig: {
ATTR_FALSE_VALUE: "suppress-warning",
},
data: function () {
return {
touches: 0,

View File

@ -1,6 +1,5 @@
@import "normalize.css/normalize.css";
@import "noty/lib/noty.css";
@import "noty/lib/themes/mint.css";
@import "vue-toastification/dist/index.css";
@import "./_variables.css";
@import "./_buttons.css";
@import "./_inputs.css";

View File

@ -1,14 +1,12 @@
import { disableExternal } from "@/utils/constants";
import { createApp } from "vue";
import Noty from "noty";
import VueLazyload from "vue-lazyload";
import Toast, { useToast } from "vue-toastification";
import createPinia from "@/stores";
import router from "@/router";
import i18n from "@/i18n";
import i18n, { rtlLanguages } from "@/i18n";
import App from "@/App.vue";
import '@/css/styles.css'
// configureCompat({ RENDER_FUNCTION: false });
import CustomToast from "@/components/CustomToast.vue";
import dayjs from "dayjs";
import localizedFormat from "dayjs/plugin/localizedFormat";
@ -24,6 +22,11 @@ const pinia = createPinia(router);
const app = createApp(App);
app.use(VueLazyload);
app.use(Toast, {
transition: "Vue-Toastification__bounce",
maxToasts: 10,
newestOnTop: true,
});
app.use(i18n);
app.use(pinia);
@ -44,54 +47,51 @@ app.directive("focus", {
},
});
const notyDefault: Noty.Options = {
type: "info",
layout: "bottomCenter",
timeout: 1000,
progressBar: true,
const toastConfig = {
position: "bottom-center",
timeout: 4000,
closeOnClick: true,
pauseOnFocusLoss: true,
pauseOnHover: true,
draggable: true,
draggablePercent: 0.6,
showCloseButtonOnHover: false,
hideProgressBar: false,
closeButton: "button",
icon: true,
};
// app.provide("$noty", (opts) => {
// new Noty(Object.assign({}, notyDefault, opts)).show();
// });
app.provide("$showSuccess", (message: any) => {
new Noty(
Object.assign({}, notyDefault, {
text: message,
type: "success",
})
).show();
app.provide("$showSuccess", (message) => {
const $toast = useToast();
$toast.success(
{
component: CustomToast,
props: {
message: message,
},
},
{ ...toastConfig, rtl: rtlLanguages.includes(i18n.global.locale) }
);
});
app.provide("$showError", (error: any, displayReport = true) => {
let btns = [
// @ts-ignore
Noty.button(i18n.global.t("buttons.close"), "", function () {
n.close();
}),
];
if (!disableExternal && displayReport) {
btns.unshift(
Noty.button(i18n.global.t("buttons.reportIssue"), "", function () {
window.open(
"https://github.com/filebrowser/filebrowser/issues/new/choose"
);
})
);
}
let n = new Noty(
Object.assign({}, notyDefault, {
text: error.message || error,
type: "error",
timeout: null,
buttons: btns,
})
app.provide("$showError", (error, displayReport = true) => {
const $toast = useToast();
$toast.error(
{
component: CustomToast,
props: {
message: error.message || error,
isReport: !disableExternal && displayReport,
// TODO: i couldnt use $t inside the component
reportText: i18n.global.t("buttons.reportIssue"),
},
},
{
...toastConfig,
timeout: 0,
rtl: rtlLanguages.includes(i18n.global.locale),
}
);
n.show();
});
router.isReady().then(() => app.mount("#app"));

View File

@ -27,6 +27,7 @@ export const useUploadStore = defineStore("upload", {
progress: [],
queue: [],
uploads: {},
error: null,
}),
getters: {
// user and jwt getter removed, no longer needed
@ -78,6 +79,9 @@ export const useUploadStore = defineStore("upload", {
const { id, loaded } = obj
this.progress[id] = loaded;
},
setError(error) {
this.error = error;
},
reset() {
this.id = 0;
this.sizes = [];
@ -140,8 +144,7 @@ export const useUploadStore = defineStore("upload", {
this.moveJob();
if (item.file.isDir) {
// TODO: find a way to display notification
await api.post(item.path).catch(console.error);
await api.post(item.path).catch(this.setError);
} else {
let onUpload = throttle(
(event) =>
@ -153,10 +156,9 @@ export const useUploadStore = defineStore("upload", {
{ leading: true, trailing: false }
);
// TODO: find a way to display notification
await api
.post(item.path, item.file, item.overwrite, onUpload)
.catch(console.error);
.catch(this.setError);
}
this.finishUpload(item);

View File

@ -25,12 +25,13 @@ import { files as api } from "@/api";
import { mapState, mapActions, mapWritableState } from "pinia";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
import { useUploadStore } from "@/stores/upload";
import HeaderBar from "@/components/header/HeaderBar.vue";
import Breadcrumbs from "@/components/Breadcrumbs.vue";
import Errors from "@/views/Errors.vue";
import Preview from "@/views/files/Preview.vue";
import Listing from "@/views/files/Listing.vue";
import FileListing from "@/views/files/FileListing.vue";
function clean(path) {
return path.endsWith("/") ? path.slice(0, -1) : path;
@ -43,7 +44,7 @@ export default {
Breadcrumbs,
Errors,
Preview,
Listing,
FileListing,
Editor: defineAsyncComponent(() => import("@/views/files/Editor.vue")),
},
data: function () {
@ -52,6 +53,7 @@ export default {
width: window.innerWidth,
};
},
inject: ["$showError"],
computed: {
...mapWritableState(useFileStore, [
"req",
@ -62,13 +64,16 @@ export default {
]),
...mapState(useLayoutStore, ["show", "showShell"]),
...mapWritableState(useLayoutStore, ["loading"]),
...mapState(useUploadStore, {
uploadError: "error",
}),
currentView() {
if (this.req.type == undefined) {
return null;
}
if (this.req.isDir) {
return "listing";
return "file-listing";
} else if (
this.req.type === "text" ||
this.req.type === "textImmutable"
@ -89,6 +94,9 @@ export default {
this.fetchData();
}
},
uploadError(newValue, oldValue) {
newValue && newValue !== oldValue && this.$showError(this.uploadError);
},
},
mounted() {
this.isFiles = true;

View File

@ -267,7 +267,6 @@
</template>
<script>
import Vue from "vue";
import { mapState, mapWritableState, mapActions, mapStores } from "pinia";
import { useAuthStore } from "@/stores/auth";
import { useClipboardStore } from "@/stores/clipboard";
@ -287,7 +286,7 @@ import Search from "@/components/Search.vue";
import Item from "@/components/files/ListingItem.vue";
export default {
name: "listing",
name: "file-listing",
components: {
HeaderBar,
Action,
@ -403,7 +402,7 @@ export default {
this.showLimit = 50;
// Ensures that the listing is displayed
Vue.nextTick(() => {
this.$nextTick(() => {
// How much every listing item affects the window height
this.setItemWeight();

View File

@ -97,7 +97,7 @@ export default {
},
inject: ["$showError", "$showSuccess"],
computed: {
...mapState(useAuthStore, ["user"]),
...mapState(useAuthStore, { sUser: "user" }),
...mapState(useLayoutStore, ["show"]),
...mapWritableState(useLayoutStore, ["loading"]),
isNew() {
@ -170,7 +170,7 @@ export default {
} else {
await api.update(user);
if (user.id === this.user.id) {
if (user.id === this.sUser.id) {
this.setUser({ ...cloneDeep(user) });
}

View File

@ -2,27 +2,24 @@ import path from "node:path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
import legacy from "@vitejs/plugin-legacy";
import { compression } from "vite-plugin-compression2";
import pluginRewriteAll from "vite-plugin-rewrite-all";
const plugins = [
vue({
template: {
compilerOptions: {
compatConfig: {
MODE: 3,
},
},
},
vue(),
VueI18nPlugin(),
legacy({
// defaults already drop IE support
targets: ["defaults"],
}),
VueI18nPlugin({}),
compression({ include: /\.js$/i, deleteOriginalAssets: true }),
pluginRewriteAll(), // fixes 404 error with paths containing dot in dev server
];
const resolve = {
alias: {
vue: "@vue/compat",
// vue: "@vue/compat",
"@/": `${path.resolve(__dirname, "src")}/`,
},
};