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",
|
||||
"vite": "^4.4.9",
|
||||
"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": {
|
||||
@ -2541,6 +2542,33 @@
|
||||
"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",
|
||||
@ -2619,6 +2647,54 @@
|
||||
"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",
|
||||
@ -2675,6 +2751,16 @@
|
||||
"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",
|
||||
@ -3301,6 +3387,12 @@
|
||||
"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",
|
||||
@ -4194,6 +4286,15 @@
|
||||
"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",
|
||||
@ -4858,6 +4959,12 @@
|
||||
"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",
|
||||
@ -6321,6 +6428,66 @@
|
||||
"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"
|
||||
},
|
||||
"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": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"serve": "vite serve",
|
||||
"build": "vite build",
|
||||
"build": "vue-tsc -p ./tsconfig.json --noEmit && vite build --emptyOutDir",
|
||||
"watch": "vite build --watch",
|
||||
"clean": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitkeep' -exec rm -r {} +",
|
||||
"lint": "eslint --ext .vue,.js src/",
|
||||
@ -56,7 +56,8 @@
|
||||
"typescript": "^5.2.2",
|
||||
"vite": "^4.4.9",
|
||||
"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": [
|
||||
"> 1%",
|
||||
|
||||
@ -179,7 +179,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module" src="/src/main.js"></script>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
|
||||
[{[ if .Theme -]}]
|
||||
<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 Layout from "@/views/Layout.vue";
|
||||
import Files from "@/views/Files.vue";
|
||||
@ -144,7 +144,7 @@ const routes = [
|
||||
},
|
||||
{
|
||||
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) {
|
||||
await new Promise((resolve) => {
|
||||
await new Promise<void>((resolve) => {
|
||||
const check = () => {
|
||||
if (typeof window.grecaptcha === "undefined") {
|
||||
setTimeout(check, 100);
|
||||
@ -175,10 +175,11 @@ const router = createRouter({
|
||||
routes,
|
||||
});
|
||||
|
||||
router.beforeResolve(async (to, from, next) => {
|
||||
router.beforeResolve(async (to: RouteLocation, from, next) => {
|
||||
let title;
|
||||
try {
|
||||
// this should not fail after we finished the migration
|
||||
// @ts-ignore
|
||||
title = i18n.global.t(titles[to.name]);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
@ -187,14 +188,14 @@ router.beforeResolve(async (to, from, next) => {
|
||||
document.title = title + " - " + name;
|
||||
|
||||
/*** 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);
|
||||
switch (true) {
|
||||
case shouldSetRtl && !rtlSet:
|
||||
document.querySelector("body").classList.add("rtl");
|
||||
document.querySelector("body")?.classList.add("rtl");
|
||||
break;
|
||||
case !shouldSetRtl && rtlSet:
|
||||
document.querySelector("body").classList.remove("rtl");
|
||||
document.querySelector("body")?.classList.remove("rtl");
|
||||
break;
|
||||
}
|
||||
|
||||
@ -225,7 +226,7 @@ router.beforeResolve(async (to, from, next) => {
|
||||
}
|
||||
|
||||
if (to.matched.some((record) => record.meta.requiresAdmin)) {
|
||||
if (!authStore.user.perm.admin) {
|
||||
if (authStore.user === null || !authStore.user.perm.admin) {
|
||||
next({ path: "/403" });
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5,7 +5,10 @@ import { cloneDeep } from "lodash-es";
|
||||
|
||||
export const useAuthStore = defineStore("auth", {
|
||||
// convert to a function
|
||||
state: () => ({
|
||||
state: (): {
|
||||
user: user | null,
|
||||
jwt: string
|
||||
} => ({
|
||||
user: null,
|
||||
jwt: "",
|
||||
}),
|
||||
@ -15,7 +18,7 @@ export const useAuthStore = defineStore("auth", {
|
||||
},
|
||||
actions: {
|
||||
// no context as first argument, use `this` instead
|
||||
setUser(value) {
|
||||
setUser(value: user) {
|
||||
if (value === null) {
|
||||
this.user = null;
|
||||
return;
|
||||
@ -23,19 +26,23 @@ export const useAuthStore = defineStore("auth", {
|
||||
|
||||
const locale = value.locale || detectLocale();
|
||||
dayjs.locale(locale);
|
||||
// @ts-ignore Don't know how to fix this yet
|
||||
i18n.global.locale.value = locale;
|
||||
this.user = value;
|
||||
},
|
||||
updateUser(value) {
|
||||
updateUser(value: user) {
|
||||
if (typeof value !== "object") return;
|
||||
|
||||
for (let field in value) {
|
||||
let field: userKey
|
||||
for (field in value) {
|
||||
if (field === "locale") {
|
||||
const locale = value[field];
|
||||
dayjs.locale(locale);
|
||||
// @ts-ignore Don't know how to fix this yet
|
||||
i18n.global.locale.value = locale;
|
||||
}
|
||||
|
||||
// @ts-ignore to fix
|
||||
this.user[field] = cloneDeep(value[field]);
|
||||
}
|
||||
},
|
||||
|
||||
@ -2,7 +2,14 @@ import { defineStore } from "pinia";
|
||||
|
||||
export const useFileStore = defineStore("file", {
|
||||
// convert to a function
|
||||
state: () => ({
|
||||
state: (): {
|
||||
req: req,
|
||||
oldReq: req,
|
||||
reload: boolean,
|
||||
selected: any[],
|
||||
multiple: boolean,
|
||||
isFiles: boolean
|
||||
} => ({
|
||||
req: {},
|
||||
oldReq: {},
|
||||
reload: false,
|
||||
@ -29,11 +36,11 @@ export const useFileStore = defineStore("file", {
|
||||
toggleMultiple() {
|
||||
this.multiple = !this.multiple;
|
||||
},
|
||||
updateRequest(value) {
|
||||
updateRequest(value: req) {
|
||||
this.oldReq = this.req;
|
||||
this.req = value;
|
||||
},
|
||||
removeSelected(value) {
|
||||
removeSelected(value: any) {
|
||||
let i = this.selected.indexOf(value);
|
||||
if (i === -1) return;
|
||||
this.selected.splice(i, 1);
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { createPinia as _createPinia } from "pinia";
|
||||
import { markRaw } from "vue";
|
||||
import { Router } from "vue-router";
|
||||
|
||||
export default function createPinia(router) {
|
||||
export default function createPinia(router: Router) {
|
||||
const pinia = _createPinia();
|
||||
pinia.use(({ store }) => {
|
||||
store.router = markRaw(router);
|
||||
|
||||
@ -4,7 +4,13 @@ import { defineStore } from "pinia";
|
||||
|
||||
export const useLayoutStore = defineStore("layout", {
|
||||
// convert to a function
|
||||
state: () => ({
|
||||
state: (): {
|
||||
loading: boolean,
|
||||
show: string | null | boolean,
|
||||
showConfirm: boolean | null,
|
||||
showAction: boolean | null,
|
||||
showShell: boolean | null
|
||||
} => ({
|
||||
loading: false,
|
||||
show: null,
|
||||
showConfirm: null,
|
||||
@ -19,7 +25,7 @@ export const useLayoutStore = defineStore("layout", {
|
||||
toggleShell() {
|
||||
this.showShell = !this.showShell;
|
||||
},
|
||||
showHover(value) {
|
||||
showHover(value: LayoutValue) {
|
||||
if (typeof value !== "object") {
|
||||
this.show = value;
|
||||
return;
|
||||
|
||||
@ -6,14 +6,21 @@ import buttons from "@/utils/buttons";
|
||||
|
||||
const UPLOADS_LIMIT = 5;
|
||||
|
||||
const beforeUnload = (event) => {
|
||||
const beforeUnload = (event: Event) => {
|
||||
event.preventDefault();
|
||||
event.returnValue = "";
|
||||
// To remove >> is deprecated
|
||||
// event.returnValue = "";
|
||||
};
|
||||
|
||||
export const useUploadStore = defineStore("upload", {
|
||||
// convert to a function
|
||||
state: () => ({
|
||||
state: (): {
|
||||
id: number,
|
||||
sizes: any[],
|
||||
progress: any[],
|
||||
queue: any[],
|
||||
uploads: uploads
|
||||
} => ({
|
||||
id: 0,
|
||||
sizes: [],
|
||||
progress: [],
|
||||
@ -29,7 +36,8 @@ export const useUploadStore = defineStore("upload", {
|
||||
|
||||
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);
|
||||
},
|
||||
filesInUploadCount: (state) => {
|
||||
@ -64,8 +72,9 @@ export const useUploadStore = defineStore("upload", {
|
||||
},
|
||||
actions: {
|
||||
// no context as first argument, use `this` instead
|
||||
setProgress({ id, loaded }) {
|
||||
setProgress(obj: { id: number, loaded: boolean }) {
|
||||
// Vue.set(this.progress, id, loaded);
|
||||
const { id, loaded } = obj
|
||||
this.progress[id] = loaded;
|
||||
},
|
||||
reset() {
|
||||
@ -73,7 +82,7 @@ export const useUploadStore = defineStore("upload", {
|
||||
this.sizes = [];
|
||||
this.progress = [];
|
||||
},
|
||||
addJob(item) {
|
||||
addJob(item: item) {
|
||||
this.queue.push(item);
|
||||
this.sizes[this.id] = item.file.size;
|
||||
this.id++;
|
||||
@ -84,11 +93,11 @@ export const useUploadStore = defineStore("upload", {
|
||||
// Vue.set(this.uploads, item.id, item);
|
||||
this.uploads[item.id] = item;
|
||||
},
|
||||
removeJob(id) {
|
||||
removeJob(id: number) {
|
||||
// Vue.delete(this.uploads, id);
|
||||
delete this.uploads[id];
|
||||
},
|
||||
upload(item) {
|
||||
upload(item: item) {
|
||||
let uploadsCount = Object.keys(this.uploads).length;
|
||||
|
||||
let isQueueEmpty = this.queue.length == 0;
|
||||
@ -102,8 +111,8 @@ export const useUploadStore = defineStore("upload", {
|
||||
this.addJob(item);
|
||||
this.processUploads();
|
||||
},
|
||||
finishUpload(item) {
|
||||
this.setProgress({ id: item.id, loaded: item.file.size });
|
||||
finishUpload(item: item) {
|
||||
this.setProgress({ id: item.id, loaded: (item.file.size > 0) });
|
||||
this.removeJob(item.id);
|
||||
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 {
|
||||
interface Window {
|
||||
FileBrowser: any;
|
||||
grecaptcha: any
|
||||
}
|
||||
}
|
||||
@ -3,9 +3,9 @@ import router from "@/router";
|
||||
import jwt_decode from "jwt-decode";
|
||||
import { baseURL } from "./constants";
|
||||
|
||||
export function parseToken(token) {
|
||||
export function parseToken(token: string) {
|
||||
// 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;`;
|
||||
|
||||
@ -19,7 +19,7 @@ export function parseToken(token) {
|
||||
export async function validateLogin() {
|
||||
try {
|
||||
if (localStorage.getItem("jwt")) {
|
||||
await renew(localStorage.getItem("jwt"));
|
||||
await renew(<string>localStorage.getItem("jwt"));
|
||||
}
|
||||
} catch (error) {
|
||||
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 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`, {
|
||||
method: "POST",
|
||||
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 res = await fetch(`${baseURL}/api/signup`, {
|
||||
@ -76,6 +76,7 @@ export async function signup(username, password) {
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
// @ts-ignore still need to fix these errors
|
||||
throw new Error(res.status);
|
||||
}
|
||||
}
|
||||
@ -86,6 +87,6 @@ export function logout() {
|
||||
const authStore = useAuthStore();
|
||||
authStore.clearUser();
|
||||
|
||||
localStorage.setItem("jwt", null);
|
||||
localStorage.setItem("jwt", '');
|
||||
router.push({ path: "/login" });
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
function loading(button) {
|
||||
let el = document.querySelector(`#${button}-button > i`);
|
||||
function loading(button: string) {
|
||||
let el: HTMLButtonElement | null = document.querySelector(`#${button}-button > i`);
|
||||
|
||||
if (el === undefined || el === null) {
|
||||
console.log("Error getting button " + button); // eslint-disable-line
|
||||
@ -11,53 +11,62 @@ function loading(button) {
|
||||
}
|
||||
|
||||
el.dataset.icon = el.innerHTML;
|
||||
el.style.opacity = 0;
|
||||
el.style.opacity = "0";
|
||||
|
||||
setTimeout(() => {
|
||||
el.classList.add("spin");
|
||||
el.innerHTML = "autorenew";
|
||||
el.style.opacity = 1;
|
||||
if(el) {
|
||||
el.classList.add("spin");
|
||||
el.innerHTML = "autorenew";
|
||||
el.style.opacity = "1";
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function done(button) {
|
||||
let el = document.querySelector(`#${button}-button > i`);
|
||||
function done(button: string) {
|
||||
let el: HTMLButtonElement | null = document.querySelector(`#${button}-button > i`);
|
||||
|
||||
if (el === undefined || el === null) {
|
||||
console.log("Error getting button " + button); // eslint-disable-line
|
||||
return;
|
||||
}
|
||||
|
||||
el.style.opacity = 0;
|
||||
el.style.opacity = "0";
|
||||
|
||||
setTimeout(() => {
|
||||
el.classList.remove("spin");
|
||||
el.innerHTML = el.dataset.icon;
|
||||
el.style.opacity = 1;
|
||||
if(el !== null) {
|
||||
el.classList.remove("spin");
|
||||
el.innerHTML = el?.dataset?.icon || "";
|
||||
el.style.opacity = "1";
|
||||
}
|
||||
|
||||
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function success(button) {
|
||||
let el = document.querySelector(`#${button}-button > i`);
|
||||
function success(button: string) {
|
||||
let el: HTMLButtonElement | null = document.querySelector(`#${button}-button > i`);
|
||||
|
||||
if (el === undefined || el === null) {
|
||||
console.log("Error getting button " + button); // eslint-disable-line
|
||||
return;
|
||||
}
|
||||
|
||||
el.style.opacity = 0;
|
||||
el.style.opacity = "0";
|
||||
|
||||
setTimeout(() => {
|
||||
el.classList.remove("spin");
|
||||
el.innerHTML = "done";
|
||||
el.style.opacity = 1;
|
||||
|
||||
if(el !== null) {
|
||||
el.classList.remove("spin");
|
||||
el.innerHTML = "done";
|
||||
el.style.opacity = "1";
|
||||
}
|
||||
setTimeout(() => {
|
||||
el.style.opacity = 0;
|
||||
if(el) el.style.opacity = "0";
|
||||
|
||||
setTimeout(() => {
|
||||
el.innerHTML = el.dataset.icon;
|
||||
el.style.opacity = 1;
|
||||
if(el !== null) {
|
||||
el.innerHTML = el?.dataset?.icon || "";
|
||||
el.style.opacity = "1";
|
||||
}
|
||||
}, 100);
|
||||
}, 500);
|
||||
}, 100);
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
export default function (name) {
|
||||
export default function (name: string) {
|
||||
let re = new RegExp(
|
||||
"(?:(?:^|.*;\\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++) {
|
||||
rules[i] = rules[i].toLowerCase();
|
||||
}
|
||||
|
||||
@ -1 +1 @@
|
||||
export * from "./funcs";
|
||||
// export * from "./funcs";
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { useUploadStore } from "@/stores/upload";
|
||||
import url from "@/utils/url";
|
||||
|
||||
export function checkConflict(files, items) {
|
||||
export function checkConflict(files: file[], items: item[]) {
|
||||
if (typeof items === "undefined" || items === null) {
|
||||
items = [];
|
||||
}
|
||||
@ -21,6 +21,7 @@ export function checkConflict(files, items) {
|
||||
}
|
||||
|
||||
let res = items.findIndex(function hasConflict(element) {
|
||||
// @ts-ignore Don't know what this does
|
||||
return element.name === this;
|
||||
}, name);
|
||||
|
||||
@ -33,10 +34,10 @@ export function checkConflict(files, items) {
|
||||
return conflict;
|
||||
}
|
||||
|
||||
export function scanFiles(dt) {
|
||||
export function scanFiles(dt: {[key: string]: any, item: item}) {
|
||||
return new Promise((resolve) => {
|
||||
let reading = 0;
|
||||
const contents = [];
|
||||
const contents: any[] = [];
|
||||
|
||||
if (dt.items !== undefined) {
|
||||
for (let item of dt.items) {
|
||||
@ -52,10 +53,10 @@ export function scanFiles(dt) {
|
||||
resolve(dt.files);
|
||||
}
|
||||
|
||||
function readEntry(entry, directory = "") {
|
||||
function readEntry(entry: any, directory = "") {
|
||||
if (entry.isFile) {
|
||||
reading++;
|
||||
entry.file((file) => {
|
||||
entry.file((file: file) => {
|
||||
reading--;
|
||||
|
||||
file.fullPath = `${directory}${file.name}`;
|
||||
@ -79,10 +80,10 @@ export function scanFiles(dt) {
|
||||
}
|
||||
}
|
||||
|
||||
function readReaderContent(reader, directory) {
|
||||
function readReaderContent(reader: any, directory: string) {
|
||||
reading++;
|
||||
|
||||
reader.readEntries(function (entries) {
|
||||
reader.readEntries(function (entries: any[]) {
|
||||
reading--;
|
||||
if (entries.length > 0) {
|
||||
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("audio")) return "audio";
|
||||
if (mimetype.startsWith("image")) return "image";
|
||||
@ -109,7 +110,7 @@ function detectType(mimetype) {
|
||||
return "blob";
|
||||
}
|
||||
|
||||
export function handleFiles(files, base, overwrite = false) {
|
||||
export function handleFiles(files: file[], base: string, overwrite = false) {
|
||||
const uploadStore = useUploadStore();
|
||||
|
||||
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("/");
|
||||
if (arr.pop() === "") {
|
||||
arr.pop();
|
||||
@ -9,7 +9,7 @@ export function removeLastDir(url) {
|
||||
|
||||
// this function is taken from mozilla
|
||||
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent#Examples
|
||||
export function encodeRFC5987ValueChars(str) {
|
||||
export function encodeRFC5987ValueChars(str: string) {
|
||||
return (
|
||||
encodeURIComponent(str)
|
||||
// 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
|
||||
.split("/")
|
||||
.map((v) => encodeURIComponent(v))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user