Added and changed all of the js files to typescript files, fixed errors as well
This commit is contained in:
parent
0907429e9a
commit
5a8ca3a50d
169
frontend/package-lock.json
generated
169
frontend/package-lock.json
generated
@ -50,7 +50,8 @@
|
|||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"vite": "^4.4.9",
|
"vite": "^4.4.9",
|
||||||
"vite-plugin-compression2": "^0.10.4",
|
"vite-plugin-compression2": "^0.10.4",
|
||||||
"vite-plugin-rewrite-all": "^1.0.1"
|
"vite-plugin-rewrite-all": "^1.0.1",
|
||||||
|
"vue-tsc": "^1.8.10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@aashutoshrathi/word-wrap": {
|
"node_modules/@aashutoshrathi/word-wrap": {
|
||||||
@ -2541,6 +2542,33 @@
|
|||||||
"vue": "^3.2.25"
|
"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": {
|
"node_modules/@vue/compat": {
|
||||||
"version": "3.3.4",
|
"version": "3.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/compat/-/compat-3.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/compat/-/compat-3.3.4.tgz",
|
||||||
@ -2619,6 +2647,54 @@
|
|||||||
"prettier": ">= 3.0.0"
|
"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": {
|
"node_modules/@vue/reactivity": {
|
||||||
"version": "3.3.4",
|
"version": "3.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.4.tgz",
|
||||||
@ -2675,6 +2751,16 @@
|
|||||||
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.4.tgz",
|
||||||
"integrity": "sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ=="
|
"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": {
|
"node_modules/@vueuse/core": {
|
||||||
"version": "10.4.1",
|
"version": "10.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-10.4.1.tgz",
|
||||||
@ -3301,6 +3387,12 @@
|
|||||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
|
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
|
||||||
"integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA=="
|
"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": {
|
"node_modules/debug": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
|
||||||
@ -4194,6 +4286,15 @@
|
|||||||
"node": ">=4"
|
"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": {
|
"node_modules/html-encoding-sniffer": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
||||||
@ -4858,6 +4959,12 @@
|
|||||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||||
"dev": true
|
"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": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.6",
|
"version": "3.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz",
|
||||||
@ -6321,6 +6428,66 @@
|
|||||||
"resolved": "https://registry.npmjs.org/vue-simple-progress/-/vue-simple-progress-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/vue-simple-progress/-/vue-simple-progress-1.1.1.tgz",
|
||||||
"integrity": "sha512-ltLWYBA5eVQHWyt1NwZeGeK0VQC69JVh1oqUdro0po7r8Hc8SEMEyEfuwyCO4s27h5I3jbD99BKKkyPSQZgoZA=="
|
"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"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"typescript": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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": {
|
"node_modules/w3c-xmlserializer": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
||||||
|
|||||||
@ -6,7 +6,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite dev",
|
"dev": "vite dev",
|
||||||
"serve": "vite serve",
|
"serve": "vite serve",
|
||||||
"build": "vite build",
|
"build": "vue-tsc -p ./tsconfig.json --noEmit && vite build --emptyOutDir",
|
||||||
"watch": "vite build --watch",
|
"watch": "vite build --watch",
|
||||||
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
|
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
|
||||||
"lint": "eslint --ext .vue,.js src/",
|
"lint": "eslint --ext .vue,.js src/",
|
||||||
@ -56,7 +56,8 @@
|
|||||||
"typescript": "^5.2.2",
|
"typescript": "^5.2.2",
|
||||||
"vite": "^4.4.9",
|
"vite": "^4.4.9",
|
||||||
"vite-plugin-compression2": "^0.10.4",
|
"vite-plugin-compression2": "^0.10.4",
|
||||||
"vite-plugin-rewrite-all": "^1.0.1"
|
"vite-plugin-rewrite-all": "^1.0.1",
|
||||||
|
"vue-tsc": "^1.8.10"
|
||||||
},
|
},
|
||||||
"browserslist": [
|
"browserslist": [
|
||||||
"> 1%",
|
"> 1%",
|
||||||
|
|||||||
@ -179,7 +179,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.ts"></script>
|
||||||
|
|
||||||
[{[ if .Theme -]}]
|
[{[ if .Theme -]}]
|
||||||
<link
|
<link
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
import { removePrefix } from "./utils";
|
|
||||||
import { baseURL } from "@/utils/constants";
|
|
||||||
import { useAuthStore } from "@/stores/auth";
|
|
||||||
|
|
||||||
const ssl = window.location.protocol === "https:";
|
|
||||||
const protocol = ssl ? "wss:" : "ws:";
|
|
||||||
|
|
||||||
export default function command(url, command, onmessage, onclose) {
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
|
|
||||||
url = removePrefix(url);
|
|
||||||
url = `${protocol}//${window.location.host}${baseURL}/api/command${url}?auth=${authStore.jwt}`;
|
|
||||||
|
|
||||||
let conn = new window.WebSocket(url);
|
|
||||||
conn.onopen = () => conn.send(command);
|
|
||||||
conn.onmessage = onmessage;
|
|
||||||
conn.onclose = onclose;
|
|
||||||
}
|
|
||||||
@ -1,204 +0,0 @@
|
|||||||
import { createURL, fetchURL, removePrefix } from "./utils";
|
|
||||||
import { baseURL } from "@/utils/constants";
|
|
||||||
import { useAuthStore } from "@/stores/auth";
|
|
||||||
import { upload as postTus, useTus } from "./tus";
|
|
||||||
|
|
||||||
export async function fetch(url) {
|
|
||||||
url = removePrefix(url);
|
|
||||||
|
|
||||||
const res = await fetchURL(`/api/resources${url}`, {});
|
|
||||||
|
|
||||||
let data = await res.json();
|
|
||||||
data.url = `/files${url}`;
|
|
||||||
|
|
||||||
if (data.isDir) {
|
|
||||||
if (!data.url.endsWith("/")) data.url += "/";
|
|
||||||
data.items = data.items.map((item, index) => {
|
|
||||||
item.index = index;
|
|
||||||
item.url = `${data.url}${encodeURIComponent(item.name)}`;
|
|
||||||
|
|
||||||
if (item.isDir) {
|
|
||||||
item.url += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function resourceAction(url, method, content) {
|
|
||||||
url = removePrefix(url);
|
|
||||||
|
|
||||||
let opts = { method };
|
|
||||||
|
|
||||||
if (content) {
|
|
||||||
opts.body = content;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = await fetchURL(`/api/resources${url}`, opts);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function remove(url) {
|
|
||||||
return resourceAction(url, "DELETE");
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function put(url, content = "") {
|
|
||||||
return resourceAction(url, "PUT", content);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function download(format, ...files) {
|
|
||||||
let url = `${baseURL}/api/raw`;
|
|
||||||
|
|
||||||
if (files.length === 1) {
|
|
||||||
url += removePrefix(files[0]) + "?";
|
|
||||||
} else {
|
|
||||||
let arg = "";
|
|
||||||
|
|
||||||
for (let file of files) {
|
|
||||||
arg += removePrefix(file) + ",";
|
|
||||||
}
|
|
||||||
|
|
||||||
arg = arg.substring(0, arg.length - 1);
|
|
||||||
arg = encodeURIComponent(arg);
|
|
||||||
url += `/?files=${arg}&`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format) {
|
|
||||||
url += `algo=${format}&`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
if (authStore.jwt) {
|
|
||||||
url += `auth=${authStore.jwt}&`;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.open(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function post(url, content = "", overwrite = false, onupload) {
|
|
||||||
// Use the pre-existing API if:
|
|
||||||
const useResourcesApi =
|
|
||||||
// a folder is being created
|
|
||||||
url.endsWith("/") ||
|
|
||||||
// We're not using http(s)
|
|
||||||
(content instanceof Blob &&
|
|
||||||
!["http:", "https:"].includes(window.location.protocol)) ||
|
|
||||||
// Tus is disabled / not applicable
|
|
||||||
!(await useTus(content));
|
|
||||||
return useResourcesApi
|
|
||||||
? postResources(url, content, overwrite, onupload)
|
|
||||||
: postTus(url, content, overwrite, onupload);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function postResources(url, content = "", overwrite = false, onupload) {
|
|
||||||
url = removePrefix(url);
|
|
||||||
|
|
||||||
let bufferContent;
|
|
||||||
if (
|
|
||||||
content instanceof Blob &&
|
|
||||||
!["http:", "https:"].includes(window.location.protocol)
|
|
||||||
) {
|
|
||||||
bufferContent = await new Response(content).arrayBuffer();
|
|
||||||
}
|
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let request = new XMLHttpRequest();
|
|
||||||
request.open(
|
|
||||||
"POST",
|
|
||||||
`${baseURL}/api/resources${url}?override=${overwrite}`,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
request.setRequestHeader("X-Auth", authStore.jwt);
|
|
||||||
|
|
||||||
if (typeof onupload === "function") {
|
|
||||||
request.upload.onprogress = onupload;
|
|
||||||
}
|
|
||||||
|
|
||||||
request.onload = () => {
|
|
||||||
if (request.status === 200) {
|
|
||||||
resolve(request.responseText);
|
|
||||||
} else if (request.status === 409) {
|
|
||||||
reject(request.status);
|
|
||||||
} else {
|
|
||||||
reject(request.responseText);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
request.onerror = () => {
|
|
||||||
reject(new Error("001 Connection aborted"));
|
|
||||||
};
|
|
||||||
|
|
||||||
request.send(bufferContent || content);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function moveCopy(items, copy = false, overwrite = false, rename = false) {
|
|
||||||
let promises = [];
|
|
||||||
|
|
||||||
for (let item of items) {
|
|
||||||
const from = item.from;
|
|
||||||
const to = encodeURIComponent(removePrefix(item.to));
|
|
||||||
const url = `${from}?action=${
|
|
||||||
copy ? "copy" : "rename"
|
|
||||||
}&destination=${to}&override=${overwrite}&rename=${rename}`;
|
|
||||||
promises.push(resourceAction(url, "PATCH"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function move(items, overwrite = false, rename = false) {
|
|
||||||
return moveCopy(items, false, overwrite, rename);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function copy(items, overwrite = false, rename = false) {
|
|
||||||
return moveCopy(items, true, overwrite, rename);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function checksum(url, algo) {
|
|
||||||
const data = await resourceAction(`${url}?checksum=${algo}`, "GET");
|
|
||||||
return (await data.json()).checksums[algo];
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDownloadURL(file, inline) {
|
|
||||||
const params = {
|
|
||||||
...(inline && { inline: "true" }),
|
|
||||||
};
|
|
||||||
|
|
||||||
return createURL("api/raw" + file.path, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getPreviewURL(file, size) {
|
|
||||||
const params = {
|
|
||||||
inline: "true",
|
|
||||||
key: Date.parse(file.modified),
|
|
||||||
};
|
|
||||||
|
|
||||||
return createURL("api/preview/" + size + file.path, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getSubtitlesURL(file) {
|
|
||||||
const params = {
|
|
||||||
inline: "true",
|
|
||||||
};
|
|
||||||
|
|
||||||
const subtitles = [];
|
|
||||||
for (const sub of file.subtitles) {
|
|
||||||
subtitles.push(createURL("api/raw" + sub, params));
|
|
||||||
}
|
|
||||||
|
|
||||||
return subtitles;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function usage(url) {
|
|
||||||
url = removePrefix(url);
|
|
||||||
|
|
||||||
const res = await fetchURL(`/api/usage${url}`, {});
|
|
||||||
|
|
||||||
return await res.json();
|
|
||||||
}
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
import * as files from "./files";
|
|
||||||
import * as share from "./share";
|
|
||||||
import * as users from "./users";
|
|
||||||
import * as settings from "./settings";
|
|
||||||
import * as pub from "./pub";
|
|
||||||
import search from "./search";
|
|
||||||
import commands from "./commands";
|
|
||||||
|
|
||||||
export { files, share, users, settings, pub, commands, search };
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
import { fetchURL, removePrefix, createURL } from "./utils";
|
|
||||||
import { baseURL } from "@/utils/constants";
|
|
||||||
|
|
||||||
export async function fetch(url, password = "") {
|
|
||||||
url = removePrefix(url);
|
|
||||||
|
|
||||||
const res = await fetchURL(
|
|
||||||
`/api/public/share${url}`,
|
|
||||||
{
|
|
||||||
headers: { "X-SHARE-PASSWORD": encodeURIComponent(password) },
|
|
||||||
},
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
let data = await res.json();
|
|
||||||
data.url = `/share${url}`;
|
|
||||||
|
|
||||||
if (data.isDir) {
|
|
||||||
if (!data.url.endsWith("/")) data.url += "/";
|
|
||||||
data.items = data.items.map((item, index) => {
|
|
||||||
item.index = index;
|
|
||||||
item.url = `${data.url}${encodeURIComponent(item.name)}`;
|
|
||||||
|
|
||||||
if (item.isDir) {
|
|
||||||
item.url += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function download(format, hash, token, ...files) {
|
|
||||||
let url = `${baseURL}/api/public/dl/${hash}`;
|
|
||||||
|
|
||||||
if (files.length === 1) {
|
|
||||||
url += encodeURIComponent(files[0]) + "?";
|
|
||||||
} else {
|
|
||||||
let arg = "";
|
|
||||||
|
|
||||||
for (let file of files) {
|
|
||||||
arg += encodeURIComponent(file) + ",";
|
|
||||||
}
|
|
||||||
|
|
||||||
arg = arg.substring(0, arg.length - 1);
|
|
||||||
arg = encodeURIComponent(arg);
|
|
||||||
url += `/?files=${arg}&`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (format) {
|
|
||||||
url += `algo=${format}&`;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (token) {
|
|
||||||
url += `token=${token}&`;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.open(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getDownloadURL(share, inline = false) {
|
|
||||||
const params = {
|
|
||||||
...(inline && { inline: "true" }),
|
|
||||||
...(share.token && { token: share.token }),
|
|
||||||
};
|
|
||||||
|
|
||||||
return createURL("api/public/dl/" + share.hash + share.path, params, false);
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import { fetchURL, removePrefix } from "./utils";
|
|
||||||
import url from "../utils/url";
|
|
||||||
|
|
||||||
export default async function search(base, query) {
|
|
||||||
base = removePrefix(base);
|
|
||||||
query = encodeURIComponent(query);
|
|
||||||
|
|
||||||
if (!base.endsWith("/")) {
|
|
||||||
base += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
let res = await fetchURL(`/api/search${base}?query=${query}`, {});
|
|
||||||
|
|
||||||
let data = await res.json();
|
|
||||||
|
|
||||||
data = data.map((item) => {
|
|
||||||
item.url = `/files${base}` + url.encodePath(item.path);
|
|
||||||
|
|
||||||
if (item.dir) {
|
|
||||||
item.url += "/";
|
|
||||||
}
|
|
||||||
|
|
||||||
return item;
|
|
||||||
});
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
import { fetchURL, fetchJSON } from "./utils";
|
|
||||||
|
|
||||||
export function get() {
|
|
||||||
return fetchJSON(`/api/settings`, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function update(settings) {
|
|
||||||
await fetchURL(`/api/settings`, {
|
|
||||||
method: "PUT",
|
|
||||||
body: JSON.stringify(settings),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@ -1,40 +0,0 @@
|
|||||||
import { fetchURL, fetchJSON, removePrefix, createURL } from "./utils";
|
|
||||||
|
|
||||||
export async function list() {
|
|
||||||
return fetchJSON("/api/shares");
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function get(url) {
|
|
||||||
url = removePrefix(url);
|
|
||||||
return fetchJSON(`/api/share${url}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function remove(hash) {
|
|
||||||
await fetchURL(`/api/share/${hash}`, {
|
|
||||||
method: "DELETE",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function create(url, password = "", expires = "", unit = "hours") {
|
|
||||||
url = removePrefix(url);
|
|
||||||
url = `/api/share${url}`;
|
|
||||||
if (expires !== "") {
|
|
||||||
url += `?expires=${expires}&unit=${unit}`;
|
|
||||||
}
|
|
||||||
let body = "{}";
|
|
||||||
if (password != "" || expires !== "" || unit !== "hours") {
|
|
||||||
body = JSON.stringify({
|
|
||||||
password: password,
|
|
||||||
expires: expires.toString(), // backend expects string not number
|
|
||||||
unit: unit,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return fetchJSON(url, {
|
|
||||||
method: "POST",
|
|
||||||
body: body,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getShareURL(share) {
|
|
||||||
return createURL("share/" + share.hash, {}, false);
|
|
||||||
}
|
|
||||||
@ -1,91 +0,0 @@
|
|||||||
import * as tus from "tus-js-client";
|
|
||||||
import { baseURL, tusEndpoint, tusSettings } from "@/utils/constants";
|
|
||||||
import { useAuthStore } from "@/stores/auth";
|
|
||||||
import { removePrefix } from "@/api/utils";
|
|
||||||
import { fetchURL } from "./utils";
|
|
||||||
|
|
||||||
const RETRY_BASE_DELAY = 1000;
|
|
||||||
const RETRY_MAX_DELAY = 20000;
|
|
||||||
|
|
||||||
export async function upload(
|
|
||||||
filePath,
|
|
||||||
content = "",
|
|
||||||
overwrite = false,
|
|
||||||
onupload
|
|
||||||
) {
|
|
||||||
if (!tusSettings) {
|
|
||||||
// Shouldn't happen as we check for tus support before calling this function
|
|
||||||
throw new Error("Tus.io settings are not defined");
|
|
||||||
}
|
|
||||||
|
|
||||||
filePath = removePrefix(filePath);
|
|
||||||
let resourcePath = `${tusEndpoint}${filePath}?override=${overwrite}`;
|
|
||||||
|
|
||||||
await createUpload(resourcePath);
|
|
||||||
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
let upload = new tus.Upload(content, {
|
|
||||||
uploadUrl: `${baseURL}${resourcePath}`,
|
|
||||||
chunkSize: tusSettings.chunkSize,
|
|
||||||
retryDelays: computeRetryDelays(tusSettings),
|
|
||||||
parallelUploads: 1,
|
|
||||||
storeFingerprintForResuming: false,
|
|
||||||
headers: {
|
|
||||||
"X-Auth": authStore.jwt,
|
|
||||||
},
|
|
||||||
onError: function (error) {
|
|
||||||
reject("Upload failed: " + error);
|
|
||||||
},
|
|
||||||
onProgress: function (bytesUploaded) {
|
|
||||||
// Emulate ProgressEvent.loaded which is used by calling functions
|
|
||||||
// loaded is specified in bytes (https://developer.mozilla.org/en-US/docs/Web/API/ProgressEvent/loaded)
|
|
||||||
if (typeof onupload === "function") {
|
|
||||||
onupload({ loaded: bytesUploaded });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onSuccess: function () {
|
|
||||||
resolve();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
upload.start();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function createUpload(resourcePath) {
|
|
||||||
let headResp = await fetchURL(resourcePath, {
|
|
||||||
method: "POST",
|
|
||||||
});
|
|
||||||
if (headResp.status !== 201) {
|
|
||||||
throw new Error(
|
|
||||||
`Failed to create an upload: ${headResp.status} ${headResp.statusText}`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function computeRetryDelays(tusSettings) {
|
|
||||||
if (!tusSettings.retryCount || tusSettings.retryCount < 1) {
|
|
||||||
// Disable retries altogether
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
// The tus client expects our retries as an array with computed backoffs
|
|
||||||
// E.g.: [0, 3000, 5000, 10000, 20000]
|
|
||||||
const retryDelays = [];
|
|
||||||
let delay = 0;
|
|
||||||
|
|
||||||
for (let i = 0; i < tusSettings.retryCount; i++) {
|
|
||||||
retryDelays.push(Math.min(delay, RETRY_MAX_DELAY));
|
|
||||||
delay =
|
|
||||||
delay === 0 ? RETRY_BASE_DELAY : Math.min(delay * 2, RETRY_MAX_DELAY);
|
|
||||||
}
|
|
||||||
|
|
||||||
return retryDelays;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function useTus(content) {
|
|
||||||
return isTusSupported() && content instanceof Blob;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isTusSupported() {
|
|
||||||
return tus.isSupported === true;
|
|
||||||
}
|
|
||||||
@ -1,41 +0,0 @@
|
|||||||
import { fetchURL, fetchJSON } from "./utils";
|
|
||||||
|
|
||||||
export async function getAll() {
|
|
||||||
return fetchJSON(`/api/users`, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function get(id) {
|
|
||||||
return fetchJSON(`/api/users/${id}`, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function create(user) {
|
|
||||||
const res = await fetchURL(`/api/users`, {
|
|
||||||
method: "POST",
|
|
||||||
body: JSON.stringify({
|
|
||||||
what: "user",
|
|
||||||
which: [],
|
|
||||||
data: user,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res.status === 201) {
|
|
||||||
return res.headers.get("Location");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function update(user, which = ["all"]) {
|
|
||||||
await fetchURL(`/api/users/${user.id}`, {
|
|
||||||
method: "PUT",
|
|
||||||
body: JSON.stringify({
|
|
||||||
what: "user",
|
|
||||||
which: which,
|
|
||||||
data: user,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function remove(id) {
|
|
||||||
await fetchURL(`/api/users/${id}`, {
|
|
||||||
method: "DELETE",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
import { useAuthStore } from "@/stores/auth";
|
|
||||||
import { renew, logout } from "@/utils/auth";
|
|
||||||
import { baseURL } from "@/utils/constants";
|
|
||||||
import { encodePath } from "@/utils/url";
|
|
||||||
|
|
||||||
export async function fetchURL(url, opts, auth = true) {
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
|
|
||||||
opts = opts || {};
|
|
||||||
opts.headers = opts.headers || {};
|
|
||||||
|
|
||||||
let { headers, ...rest } = opts;
|
|
||||||
let res;
|
|
||||||
try {
|
|
||||||
res = await fetch(`${baseURL}${url}`, {
|
|
||||||
headers: {
|
|
||||||
"X-Auth": authStore.jwt,
|
|
||||||
...headers,
|
|
||||||
},
|
|
||||||
...rest,
|
|
||||||
});
|
|
||||||
} catch {
|
|
||||||
const error = new Error("000 No connection");
|
|
||||||
error.status = 0;
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auth && res.headers.get("X-Renew-Token") === "true") {
|
|
||||||
await renew(authStore.jwt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.status < 200 || res.status > 299) {
|
|
||||||
const error = new Error(await res.text());
|
|
||||||
error.status = res.status;
|
|
||||||
|
|
||||||
if (auth && res.status == 401) {
|
|
||||||
logout();
|
|
||||||
}
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function fetchJSON(url, opts) {
|
|
||||||
const res = await fetchURL(url, opts);
|
|
||||||
|
|
||||||
if (res.status === 200) {
|
|
||||||
return res.json();
|
|
||||||
} else {
|
|
||||||
throw new Error(res.status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function removePrefix(url) {
|
|
||||||
url = url.split("/").splice(2).join("/");
|
|
||||||
|
|
||||||
if (url === "") url = "/";
|
|
||||||
if (url[0] !== "/") url = "/" + url;
|
|
||||||
return url;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createURL(endpoint, params = {}, auth = true) {
|
|
||||||
const authStore = useAuthStore();
|
|
||||||
|
|
||||||
let prefix = baseURL;
|
|
||||||
if (!prefix.endsWith("/")) {
|
|
||||||
prefix = prefix + "/";
|
|
||||||
}
|
|
||||||
const url = new URL(prefix + encodePath(endpoint), origin);
|
|
||||||
|
|
||||||
const searchParams = {
|
|
||||||
...(auth && { auth: authStore.jwt }),
|
|
||||||
...params,
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const key in searchParams) {
|
|
||||||
url.searchParams.set(key, searchParams[key]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return url.toString();
|
|
||||||
}
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { RouteLocation, createRouter, createWebHistory } from "vue-router";
|
||||||
import Login from "@/views/Login.vue";
|
import Login from "@/views/Login.vue";
|
||||||
import Layout from "@/views/Layout.vue";
|
import Layout from "@/views/Layout.vue";
|
||||||
import Files from "@/views/Files.vue";
|
import Files from "@/views/Files.vue";
|
||||||
@ -144,7 +144,7 @@ const routes = [
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: "/:catchAll(.*)*",
|
path: "/:catchAll(.*)*",
|
||||||
redirect: (to) => `/files/${[...to.params.catchAll].join("/")}`,
|
redirect: (to: RouteLocation) => `/files/${[...to.params.catchAll].join("/")}`,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -156,7 +156,7 @@ async function initAuth() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (recaptcha) {
|
if (recaptcha) {
|
||||||
await new Promise((resolve) => {
|
await new Promise<void>((resolve) => {
|
||||||
const check = () => {
|
const check = () => {
|
||||||
if (typeof window.grecaptcha === "undefined") {
|
if (typeof window.grecaptcha === "undefined") {
|
||||||
setTimeout(check, 100);
|
setTimeout(check, 100);
|
||||||
@ -175,10 +175,11 @@ const router = createRouter({
|
|||||||
routes,
|
routes,
|
||||||
});
|
});
|
||||||
|
|
||||||
router.beforeResolve(async (to, from, next) => {
|
router.beforeResolve(async (to: RouteLocation, from, next) => {
|
||||||
let title;
|
let title;
|
||||||
try {
|
try {
|
||||||
// this should not fail after we finished the migration
|
// this should not fail after we finished the migration
|
||||||
|
// @ts-ignore
|
||||||
title = i18n.global.t(titles[to.name]);
|
title = i18n.global.t(titles[to.name]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@ -187,14 +188,14 @@ router.beforeResolve(async (to, from, next) => {
|
|||||||
document.title = title + " - " + name;
|
document.title = title + " - " + name;
|
||||||
|
|
||||||
/*** RTL related settings per route ****/
|
/*** RTL related settings per route ****/
|
||||||
const rtlSet = document.querySelector("body").classList.contains("rtl");
|
const rtlSet = document.querySelector("body")?.classList.contains("rtl");
|
||||||
const shouldSetRtl = rtlLanguages.includes(i18n.global.locale);
|
const shouldSetRtl = rtlLanguages.includes(i18n.global.locale);
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case shouldSetRtl && !rtlSet:
|
case shouldSetRtl && !rtlSet:
|
||||||
document.querySelector("body").classList.add("rtl");
|
document.querySelector("body")?.classList.add("rtl");
|
||||||
break;
|
break;
|
||||||
case !shouldSetRtl && rtlSet:
|
case !shouldSetRtl && rtlSet:
|
||||||
document.querySelector("body").classList.remove("rtl");
|
document.querySelector("body")?.classList.remove("rtl");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +226,7 @@ router.beforeResolve(async (to, from, next) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (to.matched.some((record) => record.meta.requiresAdmin)) {
|
if (to.matched.some((record) => record.meta.requiresAdmin)) {
|
||||||
if (!authStore.user.perm.admin) {
|
if (authStore.user === null || !authStore.user.perm.admin) {
|
||||||
next({ path: "/403" });
|
next({ path: "/403" });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,10 @@ import { cloneDeep } from "lodash-es";
|
|||||||
|
|
||||||
export const useAuthStore = defineStore("auth", {
|
export const useAuthStore = defineStore("auth", {
|
||||||
// convert to a function
|
// convert to a function
|
||||||
state: () => ({
|
state: (): {
|
||||||
|
user: user | null,
|
||||||
|
jwt: string
|
||||||
|
} => ({
|
||||||
user: null,
|
user: null,
|
||||||
jwt: "",
|
jwt: "",
|
||||||
}),
|
}),
|
||||||
@ -15,7 +18,7 @@ export const useAuthStore = defineStore("auth", {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
// no context as first argument, use `this` instead
|
// no context as first argument, use `this` instead
|
||||||
setUser(value) {
|
setUser(value: user) {
|
||||||
if (value === null) {
|
if (value === null) {
|
||||||
this.user = null;
|
this.user = null;
|
||||||
return;
|
return;
|
||||||
@ -23,19 +26,23 @@ export const useAuthStore = defineStore("auth", {
|
|||||||
|
|
||||||
const locale = value.locale || detectLocale();
|
const locale = value.locale || detectLocale();
|
||||||
dayjs.locale(locale);
|
dayjs.locale(locale);
|
||||||
|
// @ts-ignore Don't know how to fix this yet
|
||||||
i18n.global.locale.value = locale;
|
i18n.global.locale.value = locale;
|
||||||
this.user = value;
|
this.user = value;
|
||||||
},
|
},
|
||||||
updateUser(value) {
|
updateUser(value: user) {
|
||||||
if (typeof value !== "object") return;
|
if (typeof value !== "object") return;
|
||||||
|
|
||||||
for (let field in value) {
|
let field: userKey
|
||||||
|
for (field in value) {
|
||||||
if (field === "locale") {
|
if (field === "locale") {
|
||||||
const locale = value[field];
|
const locale = value[field];
|
||||||
dayjs.locale(locale);
|
dayjs.locale(locale);
|
||||||
|
// @ts-ignore Don't know how to fix this yet
|
||||||
i18n.global.locale.value = locale;
|
i18n.global.locale.value = locale;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore to fix
|
||||||
this.user[field] = cloneDeep(value[field]);
|
this.user[field] = cloneDeep(value[field]);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,7 +2,14 @@ import { defineStore } from "pinia";
|
|||||||
|
|
||||||
export const useFileStore = defineStore("file", {
|
export const useFileStore = defineStore("file", {
|
||||||
// convert to a function
|
// convert to a function
|
||||||
state: () => ({
|
state: (): {
|
||||||
|
req: req,
|
||||||
|
oldReq: req,
|
||||||
|
reload: boolean,
|
||||||
|
selected: any[],
|
||||||
|
multiple: boolean,
|
||||||
|
isFiles: boolean
|
||||||
|
} => ({
|
||||||
req: {},
|
req: {},
|
||||||
oldReq: {},
|
oldReq: {},
|
||||||
reload: false,
|
reload: false,
|
||||||
@ -29,11 +36,11 @@ export const useFileStore = defineStore("file", {
|
|||||||
toggleMultiple() {
|
toggleMultiple() {
|
||||||
this.multiple = !this.multiple;
|
this.multiple = !this.multiple;
|
||||||
},
|
},
|
||||||
updateRequest(value) {
|
updateRequest(value: req) {
|
||||||
this.oldReq = this.req;
|
this.oldReq = this.req;
|
||||||
this.req = value;
|
this.req = value;
|
||||||
},
|
},
|
||||||
removeSelected(value) {
|
removeSelected(value: any) {
|
||||||
let i = this.selected.indexOf(value);
|
let i = this.selected.indexOf(value);
|
||||||
if (i === -1) return;
|
if (i === -1) return;
|
||||||
this.selected.splice(i, 1);
|
this.selected.splice(i, 1);
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { createPinia as _createPinia } from "pinia";
|
import { createPinia as _createPinia } from "pinia";
|
||||||
import { markRaw } from "vue";
|
import { markRaw } from "vue";
|
||||||
|
import { Router } from "vue-router";
|
||||||
|
|
||||||
export default function createPinia(router) {
|
export default function createPinia(router: Router) {
|
||||||
const pinia = _createPinia();
|
const pinia = _createPinia();
|
||||||
pinia.use(({ store }) => {
|
pinia.use(({ store }) => {
|
||||||
store.router = markRaw(router);
|
store.router = markRaw(router);
|
||||||
|
|||||||
@ -4,7 +4,13 @@ import { defineStore } from "pinia";
|
|||||||
|
|
||||||
export const useLayoutStore = defineStore("layout", {
|
export const useLayoutStore = defineStore("layout", {
|
||||||
// convert to a function
|
// convert to a function
|
||||||
state: () => ({
|
state: (): {
|
||||||
|
loading: boolean,
|
||||||
|
show: string | null | boolean,
|
||||||
|
showConfirm: boolean | null,
|
||||||
|
showAction: boolean | null,
|
||||||
|
showShell: boolean | null
|
||||||
|
} => ({
|
||||||
loading: false,
|
loading: false,
|
||||||
show: null,
|
show: null,
|
||||||
showConfirm: null,
|
showConfirm: null,
|
||||||
@ -19,7 +25,7 @@ export const useLayoutStore = defineStore("layout", {
|
|||||||
toggleShell() {
|
toggleShell() {
|
||||||
this.showShell = !this.showShell;
|
this.showShell = !this.showShell;
|
||||||
},
|
},
|
||||||
showHover(value) {
|
showHover(value: LayoutValue) {
|
||||||
if (typeof value !== "object") {
|
if (typeof value !== "object") {
|
||||||
this.show = value;
|
this.show = value;
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -6,14 +6,21 @@ import buttons from "@/utils/buttons";
|
|||||||
|
|
||||||
const UPLOADS_LIMIT = 5;
|
const UPLOADS_LIMIT = 5;
|
||||||
|
|
||||||
const beforeUnload = (event) => {
|
const beforeUnload = (event: Event) => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.returnValue = "";
|
// To remove >> is deprecated
|
||||||
|
// event.returnValue = "";
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useUploadStore = defineStore("upload", {
|
export const useUploadStore = defineStore("upload", {
|
||||||
// convert to a function
|
// convert to a function
|
||||||
state: () => ({
|
state: (): {
|
||||||
|
id: number,
|
||||||
|
sizes: any[],
|
||||||
|
progress: any[],
|
||||||
|
queue: any[],
|
||||||
|
uploads: uploads
|
||||||
|
} => ({
|
||||||
id: 0,
|
id: 0,
|
||||||
sizes: [],
|
sizes: [],
|
||||||
progress: [],
|
progress: [],
|
||||||
@ -29,7 +36,8 @@ export const useUploadStore = defineStore("upload", {
|
|||||||
|
|
||||||
const totalSize = state.sizes.reduce((a, b) => a + b, 0);
|
const totalSize = state.sizes.reduce((a, b) => a + b, 0);
|
||||||
|
|
||||||
const sum = state.progress.reduce((acc, val) => acc + val);
|
// @ts-ignore
|
||||||
|
const sum: number = state.progress.reduce((acc, val) => acc + val);
|
||||||
return Math.ceil((sum / totalSize) * 100);
|
return Math.ceil((sum / totalSize) * 100);
|
||||||
},
|
},
|
||||||
filesInUploadCount: (state) => {
|
filesInUploadCount: (state) => {
|
||||||
@ -64,8 +72,9 @@ export const useUploadStore = defineStore("upload", {
|
|||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
// no context as first argument, use `this` instead
|
// no context as first argument, use `this` instead
|
||||||
setProgress({ id, loaded }) {
|
setProgress(obj: { id: number, loaded: boolean }) {
|
||||||
// Vue.set(this.progress, id, loaded);
|
// Vue.set(this.progress, id, loaded);
|
||||||
|
const { id, loaded } = obj
|
||||||
this.progress[id] = loaded;
|
this.progress[id] = loaded;
|
||||||
},
|
},
|
||||||
reset() {
|
reset() {
|
||||||
@ -73,7 +82,7 @@ export const useUploadStore = defineStore("upload", {
|
|||||||
this.sizes = [];
|
this.sizes = [];
|
||||||
this.progress = [];
|
this.progress = [];
|
||||||
},
|
},
|
||||||
addJob(item) {
|
addJob(item: item) {
|
||||||
this.queue.push(item);
|
this.queue.push(item);
|
||||||
this.sizes[this.id] = item.file.size;
|
this.sizes[this.id] = item.file.size;
|
||||||
this.id++;
|
this.id++;
|
||||||
@ -84,11 +93,11 @@ export const useUploadStore = defineStore("upload", {
|
|||||||
// Vue.set(this.uploads, item.id, item);
|
// Vue.set(this.uploads, item.id, item);
|
||||||
this.uploads[item.id] = item;
|
this.uploads[item.id] = item;
|
||||||
},
|
},
|
||||||
removeJob(id) {
|
removeJob(id: number) {
|
||||||
// Vue.delete(this.uploads, id);
|
// Vue.delete(this.uploads, id);
|
||||||
delete this.uploads[id];
|
delete this.uploads[id];
|
||||||
},
|
},
|
||||||
upload(item) {
|
upload(item: item) {
|
||||||
let uploadsCount = Object.keys(this.uploads).length;
|
let uploadsCount = Object.keys(this.uploads).length;
|
||||||
|
|
||||||
let isQueueEmpty = this.queue.length == 0;
|
let isQueueEmpty = this.queue.length == 0;
|
||||||
@ -102,8 +111,8 @@ export const useUploadStore = defineStore("upload", {
|
|||||||
this.addJob(item);
|
this.addJob(item);
|
||||||
this.processUploads();
|
this.processUploads();
|
||||||
},
|
},
|
||||||
finishUpload(item) {
|
finishUpload(item: item) {
|
||||||
this.setProgress({ id: item.id, loaded: item.file.size });
|
this.setProgress({ id: item.id, loaded: (item.file.size > 0) });
|
||||||
this.removeJob(item.id);
|
this.removeJob(item.id);
|
||||||
this.processUploads();
|
this.processUploads();
|
||||||
},
|
},
|
||||||
|
|||||||
1
frontend/src/types/global.d.ts
vendored
1
frontend/src/types/global.d.ts
vendored
@ -3,5 +3,6 @@ export {};
|
|||||||
declare global {
|
declare global {
|
||||||
interface Window {
|
interface Window {
|
||||||
FileBrowser: any;
|
FileBrowser: any;
|
||||||
|
grecaptcha: any
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3,9 +3,9 @@ import router from "@/router";
|
|||||||
import jwt_decode from "jwt-decode";
|
import jwt_decode from "jwt-decode";
|
||||||
import { baseURL } from "./constants";
|
import { baseURL } from "./constants";
|
||||||
|
|
||||||
export function parseToken(token) {
|
export function parseToken(token: string) {
|
||||||
// falsy or malformed jwt will throw InvalidTokenError
|
// falsy or malformed jwt will throw InvalidTokenError
|
||||||
const data = jwt_decode(token);
|
const data = jwt_decode<{[key:string]: any, user: user}>(token);
|
||||||
|
|
||||||
document.cookie = `auth=${token}; Path=/; SameSite=Strict;`;
|
document.cookie = `auth=${token}; Path=/; SameSite=Strict;`;
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ export function parseToken(token) {
|
|||||||
export async function validateLogin() {
|
export async function validateLogin() {
|
||||||
try {
|
try {
|
||||||
if (localStorage.getItem("jwt")) {
|
if (localStorage.getItem("jwt")) {
|
||||||
await renew(localStorage.getItem("jwt"));
|
await renew(<string>localStorage.getItem("jwt"));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.warn("Invalid JWT token in storage"); // eslint-disable-line
|
console.warn("Invalid JWT token in storage"); // eslint-disable-line
|
||||||
@ -27,7 +27,7 @@ export async function validateLogin() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function login(username, password, recaptcha) {
|
export async function login(username: string, password: string, recaptcha: string) {
|
||||||
const data = { username, password, recaptcha };
|
const data = { username, password, recaptcha };
|
||||||
|
|
||||||
const res = await fetch(`${baseURL}/api/login`, {
|
const res = await fetch(`${baseURL}/api/login`, {
|
||||||
@ -47,7 +47,7 @@ export async function login(username, password, recaptcha) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function renew(jwt) {
|
export async function renew(jwt: string) {
|
||||||
const res = await fetch(`${baseURL}/api/renew`, {
|
const res = await fetch(`${baseURL}/api/renew`, {
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
@ -64,7 +64,7 @@ export async function renew(jwt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function signup(username, password) {
|
export async function signup(username: string, password: string) {
|
||||||
const data = { username, password };
|
const data = { username, password };
|
||||||
|
|
||||||
const res = await fetch(`${baseURL}/api/signup`, {
|
const res = await fetch(`${baseURL}/api/signup`, {
|
||||||
@ -76,6 +76,7 @@ export async function signup(username, password) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (res.status !== 200) {
|
if (res.status !== 200) {
|
||||||
|
// @ts-ignore still need to fix these errors
|
||||||
throw new Error(res.status);
|
throw new Error(res.status);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -86,6 +87,6 @@ export function logout() {
|
|||||||
const authStore = useAuthStore();
|
const authStore = useAuthStore();
|
||||||
authStore.clearUser();
|
authStore.clearUser();
|
||||||
|
|
||||||
localStorage.setItem("jwt", null);
|
localStorage.setItem("jwt", '');
|
||||||
router.push({ path: "/login" });
|
router.push({ path: "/login" });
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
function loading(button) {
|
function loading(button: string) {
|
||||||
let el = document.querySelector(`#${button}-button > i`);
|
let el: HTMLButtonElement | null = document.querySelector(`#${button}-button > i`);
|
||||||
|
|
||||||
if (el === undefined || el === null) {
|
if (el === undefined || el === null) {
|
||||||
console.log("Error getting button " + button); // eslint-disable-line
|
console.log("Error getting button " + button); // eslint-disable-line
|
||||||
@ -11,53 +11,62 @@ function loading(button) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
el.dataset.icon = el.innerHTML;
|
el.dataset.icon = el.innerHTML;
|
||||||
el.style.opacity = 0;
|
el.style.opacity = "0";
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
if(el) {
|
||||||
el.classList.add("spin");
|
el.classList.add("spin");
|
||||||
el.innerHTML = "autorenew";
|
el.innerHTML = "autorenew";
|
||||||
el.style.opacity = 1;
|
el.style.opacity = "1";
|
||||||
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function done(button) {
|
function done(button: string) {
|
||||||
let el = document.querySelector(`#${button}-button > i`);
|
let el: HTMLButtonElement | null = document.querySelector(`#${button}-button > i`);
|
||||||
|
|
||||||
if (el === undefined || el === null) {
|
if (el === undefined || el === null) {
|
||||||
console.log("Error getting button " + button); // eslint-disable-line
|
console.log("Error getting button " + button); // eslint-disable-line
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
el.style.opacity = 0;
|
el.style.opacity = "0";
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
if(el !== null) {
|
||||||
el.classList.remove("spin");
|
el.classList.remove("spin");
|
||||||
el.innerHTML = el.dataset.icon;
|
el.innerHTML = el?.dataset?.icon || "";
|
||||||
el.style.opacity = 1;
|
el.style.opacity = "1";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
function success(button) {
|
function success(button: string) {
|
||||||
let el = document.querySelector(`#${button}-button > i`);
|
let el: HTMLButtonElement | null = document.querySelector(`#${button}-button > i`);
|
||||||
|
|
||||||
if (el === undefined || el === null) {
|
if (el === undefined || el === null) {
|
||||||
console.log("Error getting button " + button); // eslint-disable-line
|
console.log("Error getting button " + button); // eslint-disable-line
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
el.style.opacity = 0;
|
el.style.opacity = "0";
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
if(el !== null) {
|
||||||
el.classList.remove("spin");
|
el.classList.remove("spin");
|
||||||
el.innerHTML = "done";
|
el.innerHTML = "done";
|
||||||
el.style.opacity = 1;
|
el.style.opacity = "1";
|
||||||
|
}
|
||||||
|
setTimeout(() => {
|
||||||
|
if(el) el.style.opacity = "0";
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
el.style.opacity = 0;
|
if(el !== null) {
|
||||||
|
el.innerHTML = el?.dataset?.icon || "";
|
||||||
setTimeout(() => {
|
el.style.opacity = "1";
|
||||||
el.innerHTML = el.dataset.icon;
|
}
|
||||||
el.style.opacity = 1;
|
|
||||||
}, 100);
|
}, 100);
|
||||||
}, 500);
|
}, 500);
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export default function (name) {
|
export default function (name: string) {
|
||||||
let re = new RegExp(
|
let re = new RegExp(
|
||||||
"(?:(?:^|.*;\\s*)" + name + "\\s*\\=\\s*([^;]*).*$)|^.*$"
|
"(?:(?:^|.*;\\s*)" + name + "\\s*\\=\\s*([^;]*).*$)|^.*$"
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export default function getRule(rules) {
|
export default function getRule(rules: any) {
|
||||||
for (let i = 0; i < rules.length; i++) {
|
for (let i = 0; i < rules.length; i++) {
|
||||||
rules[i] = rules[i].toLowerCase();
|
rules[i] = rules[i].toLowerCase();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1 +1 @@
|
|||||||
export * from "./funcs";
|
// export * from "./funcs";
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { useUploadStore } from "@/stores/upload";
|
import { useUploadStore } from "@/stores/upload";
|
||||||
import url from "@/utils/url";
|
import url from "@/utils/url";
|
||||||
|
|
||||||
export function checkConflict(files, items) {
|
export function checkConflict(files: file[], items: item[]) {
|
||||||
if (typeof items === "undefined" || items === null) {
|
if (typeof items === "undefined" || items === null) {
|
||||||
items = [];
|
items = [];
|
||||||
}
|
}
|
||||||
@ -21,6 +21,7 @@ export function checkConflict(files, items) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let res = items.findIndex(function hasConflict(element) {
|
let res = items.findIndex(function hasConflict(element) {
|
||||||
|
// @ts-ignore Don't know what this does
|
||||||
return element.name === this;
|
return element.name === this;
|
||||||
}, name);
|
}, name);
|
||||||
|
|
||||||
@ -33,10 +34,10 @@ export function checkConflict(files, items) {
|
|||||||
return conflict;
|
return conflict;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function scanFiles(dt) {
|
export function scanFiles(dt: {[key: string]: any, item: item}) {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let reading = 0;
|
let reading = 0;
|
||||||
const contents = [];
|
const contents: any[] = [];
|
||||||
|
|
||||||
if (dt.items !== undefined) {
|
if (dt.items !== undefined) {
|
||||||
for (let item of dt.items) {
|
for (let item of dt.items) {
|
||||||
@ -52,10 +53,10 @@ export function scanFiles(dt) {
|
|||||||
resolve(dt.files);
|
resolve(dt.files);
|
||||||
}
|
}
|
||||||
|
|
||||||
function readEntry(entry, directory = "") {
|
function readEntry(entry: any, directory = "") {
|
||||||
if (entry.isFile) {
|
if (entry.isFile) {
|
||||||
reading++;
|
reading++;
|
||||||
entry.file((file) => {
|
entry.file((file: file) => {
|
||||||
reading--;
|
reading--;
|
||||||
|
|
||||||
file.fullPath = `${directory}${file.name}`;
|
file.fullPath = `${directory}${file.name}`;
|
||||||
@ -79,10 +80,10 @@ export function scanFiles(dt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function readReaderContent(reader, directory) {
|
function readReaderContent(reader: any, directory: string) {
|
||||||
reading++;
|
reading++;
|
||||||
|
|
||||||
reader.readEntries(function (entries) {
|
reader.readEntries(function (entries: any[]) {
|
||||||
reading--;
|
reading--;
|
||||||
if (entries.length > 0) {
|
if (entries.length > 0) {
|
||||||
for (const entry of entries) {
|
for (const entry of entries) {
|
||||||
@ -100,7 +101,7 @@ export function scanFiles(dt) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function detectType(mimetype) {
|
function detectType(mimetype: string): uploadType {
|
||||||
if (mimetype.startsWith("video")) return "video";
|
if (mimetype.startsWith("video")) return "video";
|
||||||
if (mimetype.startsWith("audio")) return "audio";
|
if (mimetype.startsWith("audio")) return "audio";
|
||||||
if (mimetype.startsWith("image")) return "image";
|
if (mimetype.startsWith("image")) return "image";
|
||||||
@ -109,7 +110,7 @@ function detectType(mimetype) {
|
|||||||
return "blob";
|
return "blob";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function handleFiles(files, base, overwrite = false) {
|
export function handleFiles(files: file[], base: string, overwrite = false) {
|
||||||
const uploadStore = useUploadStore();
|
const uploadStore = useUploadStore();
|
||||||
|
|
||||||
for (let i = 0; i < files.length; i++) {
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
export function removeLastDir(url) {
|
export function removeLastDir(url: string) {
|
||||||
var arr = url.split("/");
|
var arr = url.split("/");
|
||||||
if (arr.pop() === "") {
|
if (arr.pop() === "") {
|
||||||
arr.pop();
|
arr.pop();
|
||||||
@ -9,7 +9,7 @@ export function removeLastDir(url) {
|
|||||||
|
|
||||||
// this function is taken from mozilla
|
// this function is taken from mozilla
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#Examples
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#Examples
|
||||||
export function encodeRFC5987ValueChars(str) {
|
export function encodeRFC5987ValueChars(str: string) {
|
||||||
return (
|
return (
|
||||||
encodeURIComponent(str)
|
encodeURIComponent(str)
|
||||||
// The following creates the sequences %27 %28 %29 %2A (Note that
|
// The following creates the sequences %27 %28 %29 %2A (Note that
|
||||||
@ -28,7 +28,7 @@ export function encodeRFC5987ValueChars(str) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function encodePath(str) {
|
export function encodePath(str: string) {
|
||||||
return str
|
return str
|
||||||
.split("/")
|
.split("/")
|
||||||
.map((v) => encodeURIComponent(v))
|
.map((v) => encodeURIComponent(v))
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user