Fix type errors reported by eslint
This commit is contained in:
parent
a066ae6c39
commit
db6b627b69
@ -3,26 +3,20 @@
|
||||
"env": {
|
||||
"node": true
|
||||
},
|
||||
"parser": "vue-eslint-parser",
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:vue/vue3-essential",
|
||||
"eslint:recommended",
|
||||
"@vue/eslint-config-typescript",
|
||||
"@vue/eslint-config-prettier"
|
||||
|
||||
],
|
||||
"rules": {
|
||||
"vue/multi-word-component-names": "off",
|
||||
"vue/no-reserved-component-names": "warn",
|
||||
"vue/no-mutating-props": "warn",
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"no-undef": "off"
|
||||
"no-undef": "error"
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": "latest",
|
||||
"sourceType": "module",
|
||||
"parser": "@typescript-eslint/parser"
|
||||
"sourceType": "module"
|
||||
}
|
||||
}
|
||||
|
||||
489
frontend/package-lock.json
generated
489
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -14,6 +14,7 @@
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@vue/eslint-config-typescript": "^11.0.3",
|
||||
"@vueuse/core": "^10.4.1",
|
||||
"ace-builds": "^1.24.1",
|
||||
"clipboard": "^2.0.11",
|
||||
@ -39,6 +40,8 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@intlify/unplugin-vue-i18n": "^0.12.3",
|
||||
"@types/lodash-es": "^4.17.9",
|
||||
"@types/node": "^20.6.0",
|
||||
"@typescript-eslint/eslint-plugin": "^6.6.0",
|
||||
"@vitejs/plugin-legacy": "^4.1.1",
|
||||
"@vitejs/plugin-vue": "^4.3.3",
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
:root {
|
||||
--background: #141D24;
|
||||
--surfacePrimary: #20292F;
|
||||
--surfaceSecondary: #3A4147;
|
||||
--background: #141d24;
|
||||
--surfacePrimary: #20292f;
|
||||
--surfaceSecondary: #3a4147;
|
||||
--divider: rgba(255, 255, 255, 0.12);
|
||||
--icon: #ffffff;
|
||||
--textPrimary: rgba(255, 255, 255, 0.87);
|
||||
@ -16,7 +16,8 @@ body {
|
||||
#loading {
|
||||
background: var(--background);
|
||||
}
|
||||
#loading .spinner div, main .spinner div {
|
||||
#loading .spinner div,
|
||||
main .spinner div {
|
||||
background: var(--icon);
|
||||
}
|
||||
|
||||
@ -56,7 +57,7 @@ header {
|
||||
color: var(--textPrimary) !important;
|
||||
}
|
||||
.action:hover {
|
||||
background-color: rgba(255, 255, 255, .1);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
.action i {
|
||||
color: var(--icon) !important;
|
||||
@ -77,7 +78,7 @@ nav > div {
|
||||
color: var(--textPrimary) !important;
|
||||
}
|
||||
.breadcrumbs a:hover {
|
||||
background-color: rgba(255, 255, 255, .1);
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
#listing .item {
|
||||
@ -141,11 +142,11 @@ nav > div {
|
||||
border-color: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
.input--red {
|
||||
background: #73302D;
|
||||
background: #73302d;
|
||||
}
|
||||
|
||||
.input--green {
|
||||
background: #147A41;
|
||||
background: #147a41;
|
||||
}
|
||||
|
||||
.dashboard #nav .wrapper,
|
||||
@ -166,7 +167,7 @@ table th {
|
||||
.file-list li:before {
|
||||
color: var(--textSecondary);
|
||||
}
|
||||
.file-list li[aria-selected=true]:before {
|
||||
.file-list li[aria-selected="true"]:before {
|
||||
color: var(--icon);
|
||||
}
|
||||
|
||||
@ -208,4 +209,4 @@ table th {
|
||||
|
||||
.share__box__element {
|
||||
border-top-color: var(--divider);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,8 +2,15 @@ import { createURL, fetchURL, removePrefix } from "./utils";
|
||||
import { baseURL } from "@/utils/constants";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { upload as postTus, useTus } from "./tus";
|
||||
import type {
|
||||
ApiContent,
|
||||
ApiMethod,
|
||||
ApiOpts,
|
||||
ChecksumAlgs,
|
||||
IFile,
|
||||
} from "@/types";
|
||||
|
||||
export async function fetch(url: ApiUrl) {
|
||||
export async function fetch(url: string) {
|
||||
url = removePrefix(url);
|
||||
|
||||
const res = await fetchURL(`/api/resources${url}`, {});
|
||||
@ -29,7 +36,7 @@ export async function fetch(url: ApiUrl) {
|
||||
return data;
|
||||
}
|
||||
|
||||
async function resourceAction(url: ApiUrl, method: ApiMethod, content?: any) {
|
||||
async function resourceAction(url: string, method: ApiMethod, content?: any) {
|
||||
url = removePrefix(url);
|
||||
|
||||
const opts: ApiOpts = {
|
||||
@ -45,11 +52,11 @@ async function resourceAction(url: ApiUrl, method: ApiMethod, content?: any) {
|
||||
return res;
|
||||
}
|
||||
|
||||
export async function remove(url: ApiUrl) {
|
||||
export async function remove(url: string) {
|
||||
return resourceAction(url, "DELETE");
|
||||
}
|
||||
|
||||
export async function put(url: ApiUrl, content = "") {
|
||||
export async function put(url: string, content = "") {
|
||||
return resourceAction(url, "PUT", content);
|
||||
}
|
||||
|
||||
@ -83,7 +90,7 @@ export function download(format: any, ...files: string[]) {
|
||||
}
|
||||
|
||||
export async function post(
|
||||
url: ApiUrl,
|
||||
url: string,
|
||||
content: ApiContent = "",
|
||||
overwrite = false,
|
||||
onupload: any = () => {}
|
||||
@ -103,7 +110,7 @@ export async function post(
|
||||
}
|
||||
|
||||
async function postResources(
|
||||
url: ApiUrl,
|
||||
url: string,
|
||||
content: ApiContent = "",
|
||||
overwrite = false,
|
||||
onupload: any
|
||||
@ -178,7 +185,7 @@ export function copy(items: any[], overwrite = false, rename = false) {
|
||||
return moveCopy(items, true, overwrite, rename);
|
||||
}
|
||||
|
||||
export async function checksum(url: ApiUrl, algo: algo) {
|
||||
export async function checksum(url: string, algo: ChecksumAlgs) {
|
||||
const data = await resourceAction(`${url}?checksum=${algo}`, "GET");
|
||||
return (await data.json()).checksums[algo];
|
||||
}
|
||||
@ -213,7 +220,7 @@ export function getSubtitlesURL(file: IFile) {
|
||||
return subtitles;
|
||||
}
|
||||
|
||||
export async function usage(url: ApiUrl) {
|
||||
export async function usage(url: string) {
|
||||
url = removePrefix(url);
|
||||
|
||||
const res = await fetchURL(`/api/usage${url}`, {});
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import type { IFile } from "@/types";
|
||||
import { fetchURL, removePrefix, createURL } from "./utils";
|
||||
import { baseURL } from "@/utils/constants";
|
||||
|
||||
export async function fetch(url: ApiUrl, password: string = "") {
|
||||
export async function fetch(url: string, password: string = "") {
|
||||
url = removePrefix(url);
|
||||
|
||||
const res = await fetchURL(
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { fetchURL, removePrefix } from "./utils";
|
||||
import url from "../utils/url";
|
||||
import type { Item } from "@/types";
|
||||
|
||||
export default async function search(base: apiUrl, query: string) {
|
||||
export default async function search(base: string, query: string) {
|
||||
base = removePrefix(base);
|
||||
query = encodeURIComponent(query);
|
||||
|
||||
@ -13,7 +14,7 @@ export default async function search(base: apiUrl, query: string) {
|
||||
|
||||
let data = await res.json();
|
||||
|
||||
data = data.map((item: item) => {
|
||||
data = data.map((item: Item) => {
|
||||
item.url = `/files${base}` + url.encodePath(item.path);
|
||||
|
||||
if (item.dir) {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { ISettings } from "@/types";
|
||||
import { fetchURL, fetchJSON } from "./utils";
|
||||
|
||||
export function get() {
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
import type { Share } from "@/types";
|
||||
import { fetchURL, fetchJSON, removePrefix, createURL } from "./utils";
|
||||
|
||||
export async function list() {
|
||||
return fetchJSON("/api/shares");
|
||||
}
|
||||
|
||||
export async function get(url: apiUrl) {
|
||||
export async function get(url: string) {
|
||||
url = removePrefix(url);
|
||||
return fetchJSON(`/api/share${url}`);
|
||||
}
|
||||
@ -16,7 +17,7 @@ export async function remove(hash: string) {
|
||||
}
|
||||
|
||||
export async function create(
|
||||
url: apiUrl,
|
||||
url: string,
|
||||
password = "",
|
||||
expires = "",
|
||||
unit = "hours"
|
||||
@ -40,6 +41,6 @@ export async function create(
|
||||
});
|
||||
}
|
||||
|
||||
export function getShareURL(share: share) {
|
||||
export function getShareURL(share: Share) {
|
||||
return createURL("share/" + share.hash, {}, false);
|
||||
}
|
||||
|
||||
@ -3,6 +3,7 @@ import { baseURL, tusEndpoint, tusSettings } from "@/utils/constants";
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import { removePrefix } from "@/api/utils";
|
||||
import { fetchURL } from "./utils";
|
||||
import type { ApiContent, TusSettings } from "@/types";
|
||||
|
||||
const RETRY_BASE_DELAY = 1000;
|
||||
const RETRY_MAX_DELAY = 20000;
|
||||
@ -57,7 +58,7 @@ export async function upload(
|
||||
});
|
||||
}
|
||||
|
||||
async function createUpload(resourcePath: resourcePath) {
|
||||
async function createUpload(resourcePath: string) {
|
||||
const headResp = await fetchURL(resourcePath, {
|
||||
method: "POST",
|
||||
});
|
||||
@ -68,7 +69,7 @@ async function createUpload(resourcePath: resourcePath) {
|
||||
}
|
||||
}
|
||||
|
||||
function computeRetryDelays(tusSettings: tusSettings): number[] | undefined {
|
||||
function computeRetryDelays(tusSettings: TusSettings): number[] | undefined {
|
||||
if (!tusSettings.retryCount || tusSettings.retryCount < 1) {
|
||||
// Disable retries altogether
|
||||
return undefined;
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { User } from "@/types/user";
|
||||
import { fetchURL, fetchJSON } from "./utils";
|
||||
|
||||
export async function getAll() {
|
||||
@ -8,7 +9,7 @@ export async function get(id: number) {
|
||||
return fetchJSON(`/api/users/${id}`, {});
|
||||
}
|
||||
|
||||
export async function create(user: user) {
|
||||
export async function create(user: User) {
|
||||
const res = await fetchURL(`/api/users`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
@ -23,7 +24,7 @@ export async function create(user: user) {
|
||||
}
|
||||
}
|
||||
|
||||
export async function update(user: user, which = ["all"]) {
|
||||
export async function update(user: User, which = ["all"]) {
|
||||
await fetchURL(`/api/users/${user.id}`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({
|
||||
|
||||
@ -1,9 +1,20 @@
|
||||
import { useAuthStore } from "@/stores/auth";
|
||||
import type { ApiOpts, SearchParams } from "@/types";
|
||||
import { renew, logout } from "@/utils/auth";
|
||||
import { baseURL } from "@/utils/constants";
|
||||
import { encodePath } from "@/utils/url";
|
||||
|
||||
export async function fetchURL(url: ApiUrl, opts: ApiOpts, auth = true) {
|
||||
export class StatusError extends Error {
|
||||
constructor(
|
||||
message: any,
|
||||
public status?: number
|
||||
) {
|
||||
super(message);
|
||||
this.name = "StatusError";
|
||||
}
|
||||
}
|
||||
|
||||
export async function fetchURL(url: string, opts: ApiOpts, auth = true) {
|
||||
const authStore = useAuthStore();
|
||||
|
||||
opts = opts || {};
|
||||
@ -20,11 +31,7 @@ export async function fetchURL(url: ApiUrl, opts: ApiOpts, auth = true) {
|
||||
...rest,
|
||||
});
|
||||
} catch {
|
||||
const error = new Error("000 No connection");
|
||||
// @ts-ignore don't know yet how to solve
|
||||
error.status = 0;
|
||||
|
||||
throw error;
|
||||
throw new StatusError("000 No connection", 0);
|
||||
}
|
||||
|
||||
if (auth && res.headers.get("X-Renew-Token") === "true") {
|
||||
@ -32,9 +39,7 @@ export async function fetchURL(url: ApiUrl, opts: ApiOpts, auth = true) {
|
||||
}
|
||||
|
||||
if (res.status < 200 || res.status > 299) {
|
||||
const error = new Error(await res.text());
|
||||
// @ts-ignore don't know yet how to solve
|
||||
error.status = res.status;
|
||||
const error = new StatusError(await res.text(), res.status);
|
||||
|
||||
if (auth && res.status == 401) {
|
||||
logout();
|
||||
@ -46,7 +51,7 @@ export async function fetchURL(url: ApiUrl, opts: ApiOpts, auth = true) {
|
||||
return res;
|
||||
}
|
||||
|
||||
export async function fetchJSON(url: ApiUrl, opts?: any) {
|
||||
export async function fetchJSON(url: string, opts?: any) {
|
||||
const res = await fetchURL(url, opts);
|
||||
|
||||
if (res.status === 200) {
|
||||
@ -56,7 +61,7 @@ export async function fetchJSON(url: ApiUrl, opts?: any) {
|
||||
}
|
||||
}
|
||||
|
||||
export function removePrefix(url: ApiUrl) {
|
||||
export function removePrefix(url: string) {
|
||||
url = url.split("/").splice(2).join("/");
|
||||
|
||||
if (url === "") url = "/";
|
||||
@ -64,7 +69,7 @@ export function removePrefix(url: ApiUrl) {
|
||||
return url;
|
||||
}
|
||||
|
||||
export function createURL(endpoint: ApiUrl, params = {}, auth = true) {
|
||||
export function createURL(endpoint: string, params = {}, auth = true) {
|
||||
const authStore = useAuthStore();
|
||||
|
||||
let prefix = baseURL;
|
||||
@ -73,7 +78,7 @@ export function createURL(endpoint: ApiUrl, params = {}, auth = true) {
|
||||
}
|
||||
const url = new URL(prefix + encodePath(endpoint), origin);
|
||||
|
||||
const searchParams: searchParams = {
|
||||
const searchParams: SearchParams = {
|
||||
...(auth && { auth: authStore.jwt }),
|
||||
...params,
|
||||
};
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
// @ts-nocheck
|
||||
import { disableExternal } from "@/utils/constants";
|
||||
import { createApp } from "vue";
|
||||
import VueLazyload from "vue-lazyload";
|
||||
@ -64,7 +63,7 @@ const toastConfig = {
|
||||
icon: true,
|
||||
};
|
||||
|
||||
app.provide("$showSuccess", (message) => {
|
||||
app.provide("$showSuccess", (message: string) => {
|
||||
const $toast = useToast();
|
||||
$toast.success(
|
||||
{
|
||||
@ -73,22 +72,27 @@ app.provide("$showSuccess", (message) => {
|
||||
message: message,
|
||||
},
|
||||
},
|
||||
// their type defs are messed up
|
||||
//@ts-ignore
|
||||
{ ...toastConfig, rtl: rtlLanguages.includes(i18n.global.locale) }
|
||||
);
|
||||
});
|
||||
|
||||
app.provide("$showError", (error, displayReport = true) => {
|
||||
app.provide("$showError", (error: Error | string, displayReport = true) => {
|
||||
const $toast = useToast();
|
||||
$toast.error(
|
||||
{
|
||||
component: CustomToast,
|
||||
props: {
|
||||
message: error.message || error,
|
||||
message: (error as Error).message || error,
|
||||
isReport: !disableExternal && displayReport,
|
||||
// TODO: i couldnt use $t inside the component
|
||||
//@ts-ignore
|
||||
reportText: i18n.global.t("buttons.reportIssue"),
|
||||
},
|
||||
},
|
||||
// their type defs are messed up
|
||||
//@ts-ignore
|
||||
{
|
||||
...toastConfig,
|
||||
timeout: 0,
|
||||
|
||||
@ -176,12 +176,10 @@ const router = createRouter({
|
||||
routes,
|
||||
});
|
||||
|
||||
router.beforeResolve(async (to: RouteLocation, from, next) => {
|
||||
router.beforeResolve(async (to, from, next) => {
|
||||
let title;
|
||||
try {
|
||||
// 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 as keyof typeof titles]);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
// @ts-nocheck
|
||||
import type { User } from "@/types";
|
||||
import { defineStore } from "pinia";
|
||||
import dayjs from "dayjs";
|
||||
import i18n, { detectLocale } from "@/i18n";
|
||||
@ -7,7 +7,7 @@ import { cloneDeep } from "lodash-es";
|
||||
export const useAuthStore = defineStore("auth", {
|
||||
// convert to a function
|
||||
state: (): {
|
||||
user: user | null;
|
||||
user: User | null;
|
||||
jwt: string;
|
||||
} => ({
|
||||
user: null,
|
||||
@ -19,7 +19,7 @@ export const useAuthStore = defineStore("auth", {
|
||||
},
|
||||
actions: {
|
||||
// no context as first argument, use `this` instead
|
||||
setUser(value: user) {
|
||||
setUser(value: User) {
|
||||
if (value === null) {
|
||||
this.user = null;
|
||||
return;
|
||||
@ -27,25 +27,16 @@ 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;
|
||||
// according to doc u only need .value if legacy: false
|
||||
// in createI18n but they lied
|
||||
// https://vue-i18n.intlify.dev/guide/essentials/scope.html#local-scope-1
|
||||
//@ts-ignore
|
||||
i18n.global.locale = locale;
|
||||
this.user = value;
|
||||
},
|
||||
updateUser(value: user) {
|
||||
if (typeof value !== "object") return;
|
||||
|
||||
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]);
|
||||
}
|
||||
updateUser(value: User) {
|
||||
if (typeof value !== "object" || !value) return;
|
||||
this.setUser(cloneDeep(value));
|
||||
},
|
||||
// easily reset state using `$reset`
|
||||
clearUser() {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { IFile } from "@/types";
|
||||
import { defineStore } from "pinia";
|
||||
|
||||
export const useFileStore = defineStore("file", {
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import type { LayoutValue } from "@/types";
|
||||
import { defineStore } from "pinia";
|
||||
// import { useAuthPreferencesStore } from "./auth-preferences";
|
||||
// import { useAuthEmailStore } from "./auth-email";
|
||||
@ -39,7 +40,7 @@ export const useLayoutStore = defineStore("layout", {
|
||||
},
|
||||
showError() {
|
||||
this.show = "error";
|
||||
console.error(' error')
|
||||
console.error(" error");
|
||||
},
|
||||
showSuccess() {
|
||||
this.show = "success";
|
||||
|
||||
@ -1,10 +1,11 @@
|
||||
// @ts-nocheck
|
||||
import { defineStore } from "pinia";
|
||||
import { useFileStore } from "./file";
|
||||
import { files as api } from "@/api";
|
||||
import throttle from "lodash/throttle";
|
||||
import buttons from "@/utils/buttons";
|
||||
import type { Item, Uploads } from "@/types";
|
||||
|
||||
// TODO: make this into a user setting
|
||||
const UPLOADS_LIMIT = 5;
|
||||
|
||||
const beforeUnload = (event: Event) => {
|
||||
@ -20,8 +21,8 @@ export const useUploadStore = defineStore("upload", {
|
||||
sizes: any[];
|
||||
progress: any[];
|
||||
queue: any[];
|
||||
uploads: uploads;
|
||||
error: any;
|
||||
uploads: Uploads;
|
||||
error: Error | null;
|
||||
} => ({
|
||||
id: 0,
|
||||
sizes: [],
|
||||
@ -39,7 +40,6 @@ export const useUploadStore = defineStore("upload", {
|
||||
|
||||
const totalSize = state.sizes.reduce((a, b) => a + b, 0);
|
||||
|
||||
// @ts-ignore
|
||||
const sum: number = state.progress.reduce((acc, val) => acc + val);
|
||||
return Math.ceil((sum / totalSize) * 100);
|
||||
},
|
||||
@ -80,7 +80,7 @@ export const useUploadStore = defineStore("upload", {
|
||||
const { id, loaded } = obj;
|
||||
this.progress[id] = loaded;
|
||||
},
|
||||
setError(error) {
|
||||
setError(error: Error) {
|
||||
this.error = error;
|
||||
},
|
||||
reset() {
|
||||
@ -88,7 +88,7 @@ export const useUploadStore = defineStore("upload", {
|
||||
this.sizes = [];
|
||||
this.progress = [];
|
||||
},
|
||||
addJob(item: item) {
|
||||
addJob(item: Item) {
|
||||
this.queue.push(item);
|
||||
this.sizes[this.id] = item.file.size;
|
||||
this.id++;
|
||||
@ -103,7 +103,7 @@ export const useUploadStore = defineStore("upload", {
|
||||
// Vue.delete(this.uploads, id);
|
||||
delete this.uploads[id];
|
||||
},
|
||||
upload(item: item) {
|
||||
upload(item: Item) {
|
||||
const uploadsCount = Object.keys(this.uploads).length;
|
||||
|
||||
const isQueueEmpty = this.queue.length == 0;
|
||||
@ -117,7 +117,7 @@ export const useUploadStore = defineStore("upload", {
|
||||
this.addJob(item);
|
||||
this.processUploads();
|
||||
},
|
||||
finishUpload(item: item) {
|
||||
finishUpload(item: Item) {
|
||||
this.setProgress({ id: item.id, loaded: item.file.size > 0 });
|
||||
this.removeJob(item.id);
|
||||
this.processUploads();
|
||||
|
||||
20
frontend/src/types/api.d.ts
vendored
20
frontend/src/types/api.d.ts
vendored
@ -1,31 +1,27 @@
|
||||
type ApiUrl = string; // Can also be set as a path eg: "path1" | "path2"
|
||||
export type ApiMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
||||
|
||||
type resourcePath = string;
|
||||
|
||||
type ApiMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
|
||||
|
||||
type ApiContent =
|
||||
export type ApiContent =
|
||||
| Blob
|
||||
| File
|
||||
| Pick<ReadableStreamDefaultReader<any>, "read">
|
||||
| "";
|
||||
|
||||
interface ApiOpts {
|
||||
export interface ApiOpts {
|
||||
method?: ApiMethod;
|
||||
headers?: object;
|
||||
body?: any;
|
||||
}
|
||||
|
||||
interface tusSettings {
|
||||
export interface TusSettings {
|
||||
retryCount: number;
|
||||
chunkSize: number;
|
||||
}
|
||||
|
||||
type algo = any;
|
||||
export type ChecksumAlgs = "md5" | "sha1" | "sha256" | "sha512";
|
||||
|
||||
type inline = any;
|
||||
|
||||
interface share {
|
||||
export interface Share {
|
||||
expire: any;
|
||||
hash: string;
|
||||
path: string;
|
||||
@ -37,4 +33,6 @@ interface settings {
|
||||
any;
|
||||
}
|
||||
|
||||
type searchParams = any;
|
||||
export interface SearchParams {
|
||||
[key: string]: string;
|
||||
}
|
||||
|
||||
24
frontend/src/types/file.d.ts
vendored
24
frontend/src/types/file.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
interface IFile {
|
||||
export interface IFile {
|
||||
index?: number;
|
||||
name: string;
|
||||
modified: string;
|
||||
@ -7,14 +7,14 @@ interface IFile {
|
||||
isDir: boolean;
|
||||
size: number;
|
||||
fullPath: string;
|
||||
type: uploadType;
|
||||
type: FileType;
|
||||
items: IFile[];
|
||||
token?: string;
|
||||
hash: string;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
type uploadType =
|
||||
export type FileType =
|
||||
| "video"
|
||||
| "audio"
|
||||
| "image"
|
||||
@ -37,12 +37,22 @@ type req = {
|
||||
hash: string;
|
||||
};
|
||||
|
||||
interface uploads {
|
||||
[key: string]: upload;
|
||||
export interface Uploads {
|
||||
[key: string]: Upload;
|
||||
}
|
||||
|
||||
interface upload {
|
||||
export interface Upload {
|
||||
id: number;
|
||||
file: file;
|
||||
file: IFile;
|
||||
type: string;
|
||||
}
|
||||
|
||||
export interface Item {
|
||||
id: number;
|
||||
url?: string;
|
||||
path: string;
|
||||
file: IFile;
|
||||
dir?: boolean;
|
||||
overwrite?: boolean;
|
||||
type?: FileType;
|
||||
}
|
||||
|
||||
6
frontend/src/types/index.d.ts
vendored
Normal file
6
frontend/src/types/index.d.ts
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
export * from "./api";
|
||||
export * from "./file";
|
||||
export * from "./layout";
|
||||
export * from "./settings";
|
||||
export * from "./toast";
|
||||
export * from "./user";
|
||||
2
frontend/src/types/layout.d.ts
vendored
2
frontend/src/types/layout.d.ts
vendored
@ -1,4 +1,4 @@
|
||||
interface LayoutValue {
|
||||
export interface LayoutValue {
|
||||
prompt: string;
|
||||
confirm: any;
|
||||
action?: boolean;
|
||||
|
||||
23
frontend/src/types/settings.d.ts
vendored
23
frontend/src/types/settings.d.ts
vendored
@ -1,8 +1,10 @@
|
||||
interface ISettings {
|
||||
import type { Permissions } from "./user";
|
||||
|
||||
export interface ISettings {
|
||||
signup: boolean;
|
||||
createUserDir: boolean;
|
||||
userHomeBasePath: string;
|
||||
defaults: Defaults;
|
||||
defaults: SettingsDefaults;
|
||||
rules: any[];
|
||||
branding: SettingsBranding;
|
||||
tus: SettingsTus;
|
||||
@ -16,7 +18,7 @@ interface SettingsDefaults {
|
||||
viewMode: string;
|
||||
singleClick: boolean;
|
||||
sorting: SettingsSorting;
|
||||
perm: SettingsPerm;
|
||||
perm: Permissions;
|
||||
commands: any[];
|
||||
hideDotfiles: boolean;
|
||||
dateFormat: boolean;
|
||||
@ -27,17 +29,6 @@ interface SettingsSorting {
|
||||
asc: boolean;
|
||||
}
|
||||
|
||||
interface SettingsPerm {
|
||||
admin: boolean;
|
||||
execute: boolean;
|
||||
create: boolean;
|
||||
rename: boolean;
|
||||
modify: boolean;
|
||||
delete: boolean;
|
||||
share: boolean;
|
||||
download: boolean;
|
||||
}
|
||||
|
||||
interface SettingsBranding {
|
||||
name: string;
|
||||
disableExternal: boolean;
|
||||
@ -52,7 +43,7 @@ interface SettingsTus {
|
||||
retryCount: number;
|
||||
}
|
||||
|
||||
interface SettingsCommand {
|
||||
export interface SettingsCommand {
|
||||
after_copy?: string[];
|
||||
after_delete?: string[];
|
||||
after_rename?: string[];
|
||||
@ -65,7 +56,7 @@ interface SettingsCommand {
|
||||
before_upload?: string[];
|
||||
}
|
||||
|
||||
interface SettingsUnit {
|
||||
export interface SettingsUnit {
|
||||
KB: number;
|
||||
MB: number;
|
||||
GB: number;
|
||||
|
||||
6
frontend/src/types/toast.d.ts
vendored
6
frontend/src/types/toast.d.ts
vendored
@ -1 +1,5 @@
|
||||
type TToast = (message: string) => void;
|
||||
export type IToastSuccess = (message: string) => void;
|
||||
export type IToastError = (
|
||||
error: Error | string,
|
||||
displayReport?: boolean
|
||||
) => void;
|
||||
|
||||
19
frontend/src/types/user.d.ts
vendored
19
frontend/src/types/user.d.ts
vendored
@ -1,7 +1,20 @@
|
||||
interface user {
|
||||
export interface User {
|
||||
id: number;
|
||||
locale: string;
|
||||
perm: any;
|
||||
perm: Permissions;
|
||||
}
|
||||
|
||||
type userKey = keyof user;
|
||||
export interface Permissions {
|
||||
admin: boolean;
|
||||
copy: boolean;
|
||||
create: boolean;
|
||||
delete: boolean;
|
||||
download: boolean;
|
||||
execute: boolean;
|
||||
modify: boolean;
|
||||
move: boolean;
|
||||
rename: boolean;
|
||||
share: boolean;
|
||||
shell: boolean;
|
||||
upload: boolean;
|
||||
}
|
||||
|
||||
@ -2,10 +2,12 @@ import { useAuthStore } from "@/stores/auth";
|
||||
import router from "@/router";
|
||||
import jwt_decode from "jwt-decode";
|
||||
import { baseURL } from "./constants";
|
||||
import { StatusError } from "@/api/utils";
|
||||
import type { User } from "@/types";
|
||||
|
||||
export function parseToken(token: string) {
|
||||
// falsy or malformed jwt will throw InvalidTokenError
|
||||
const data = jwt_decode<{ [key: string]: any; user: user }>(token);
|
||||
const data = jwt_decode<{ [key: string]: any; user: User }>(token);
|
||||
|
||||
document.cookie = `auth=${token}; Path=/; SameSite=Strict;`;
|
||||
|
||||
@ -80,8 +82,7 @@ export async function signup(username: string, password: string) {
|
||||
});
|
||||
|
||||
if (res.status !== 200) {
|
||||
// @ts-ignore still need to fix these errors
|
||||
throw new Error(res.status);
|
||||
throw new StatusError(res.statusText, res.status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
import { useUploadStore } from "@/stores/upload";
|
||||
import type { IFile, Item, FileType } from "@/types";
|
||||
import url from "@/utils/url";
|
||||
|
||||
export function checkConflict(files: file[], items: item[]) {
|
||||
export function checkConflict(files: IFile[], items: Item[]) {
|
||||
if (typeof items === "undefined" || items === null) {
|
||||
items = [];
|
||||
}
|
||||
@ -34,7 +35,7 @@ export function checkConflict(files: file[], items: item[]) {
|
||||
return conflict;
|
||||
}
|
||||
|
||||
export function scanFiles(dt: { [key: string]: any; item: item }) {
|
||||
export function scanFiles(dt: { [key: string]: any; item: Item }) {
|
||||
return new Promise((resolve) => {
|
||||
let reading = 0;
|
||||
const contents: any[] = [];
|
||||
@ -56,7 +57,7 @@ export function scanFiles(dt: { [key: string]: any; item: item }) {
|
||||
function readEntry(entry: any, directory = "") {
|
||||
if (entry.isFile) {
|
||||
reading++;
|
||||
entry.file((file: file) => {
|
||||
entry.file((file: IFile) => {
|
||||
reading--;
|
||||
|
||||
file.fullPath = `${directory}${file.name}`;
|
||||
@ -101,7 +102,7 @@ export function scanFiles(dt: { [key: string]: any; item: item }) {
|
||||
});
|
||||
}
|
||||
|
||||
function detectType(mimetype: string): uploadType {
|
||||
function detectType(mimetype: string): FileType {
|
||||
if (mimetype.startsWith("video")) return "video";
|
||||
if (mimetype.startsWith("audio")) return "audio";
|
||||
if (mimetype.startsWith("image")) return "image";
|
||||
@ -110,7 +111,7 @@ function detectType(mimetype: string): uploadType {
|
||||
return "blob";
|
||||
}
|
||||
|
||||
export function handleFiles(files: file[], base: string, overwrite = false) {
|
||||
export function handleFiles(files: IFile[], base: string, overwrite = false) {
|
||||
const uploadStore = useUploadStore();
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
@ -128,7 +129,7 @@ export function handleFiles(files: file[], base: string, overwrite = false) {
|
||||
path += "/";
|
||||
}
|
||||
|
||||
const item = {
|
||||
const item: Item = {
|
||||
id,
|
||||
path,
|
||||
file,
|
||||
|
||||
@ -1,67 +0,0 @@
|
||||
import Vue from "vue";
|
||||
import Noty from "noty";
|
||||
import VueLazyload from "vue-lazyload";
|
||||
// @ts-ignore
|
||||
import i18n from "@/i18n";
|
||||
import { disableExternal } from "@/utils/constants";
|
||||
|
||||
Vue.use(VueLazyload);
|
||||
|
||||
Vue.config.productionTip = true;
|
||||
|
||||
const notyDefault = {
|
||||
type: "info",
|
||||
layout: "bottomRight",
|
||||
timeout: 1000,
|
||||
progressBar: true,
|
||||
};
|
||||
|
||||
Vue.prototype.$noty = (opts) => {
|
||||
new Noty(Object.assign({}, notyDefault, opts)).show();
|
||||
};
|
||||
|
||||
Vue.prototype.$showSuccess = (message) => {
|
||||
new Noty(
|
||||
Object.assign({}, notyDefault, {
|
||||
text: message,
|
||||
type: "success",
|
||||
})
|
||||
).show();
|
||||
};
|
||||
|
||||
Vue.prototype.$showError = (error, displayReport = true) => {
|
||||
let btns = [
|
||||
Noty.button(i18n.t("buttons.close"), "", function () {
|
||||
n.close();
|
||||
}),
|
||||
];
|
||||
|
||||
if (!disableExternal && displayReport) {
|
||||
btns.unshift(
|
||||
Noty.button(i18n.t("buttons.reportIssue"), "", function () {
|
||||
window.open(
|
||||
"https://github.com/filebrowser/filebrowser/issues/new/choose"
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
let n = new Noty(
|
||||
Object.assign({}, notyDefault, {
|
||||
text: error.message || error,
|
||||
type: "error",
|
||||
timeout: null,
|
||||
buttons: btns,
|
||||
})
|
||||
);
|
||||
|
||||
n.show();
|
||||
};
|
||||
|
||||
Vue.directive("focus", {
|
||||
inserted: function (el) {
|
||||
el.focus();
|
||||
},
|
||||
});
|
||||
|
||||
export default Vue;
|
||||
@ -239,6 +239,13 @@ import Themes from "@/components/settings/Themes.vue";
|
||||
import Errors from "@/views/Errors.vue";
|
||||
import { computed, inject, onBeforeUnmount, onMounted, ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import type {
|
||||
ISettings,
|
||||
IToastError,
|
||||
IToastSuccess,
|
||||
SettingsCommand,
|
||||
SettingsUnit,
|
||||
} from "@/types";
|
||||
|
||||
const error = ref<any>(null);
|
||||
const originalSettings = ref<ISettings | null>(null);
|
||||
@ -248,10 +255,10 @@ const debounceTimeout = ref<number | null>(null);
|
||||
const commandObject = ref<{
|
||||
[key in keyof SettingsCommand]: string;
|
||||
}>({});
|
||||
const shellValue = ref<string>("")
|
||||
const shellValue = ref<string>("");
|
||||
|
||||
const $showError = inject<TToast>("$showError") as TToast;
|
||||
const $showSuccess = inject<TToast>("$showSuccess") as TToast;
|
||||
const $showSuccess = inject<IToastSuccess>("$showSuccess") as IToastSuccess;
|
||||
const $showError = inject<IToastError>("$showError") as IToastError;
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
@ -307,16 +314,16 @@ const save = async () => {
|
||||
// @ts-ignore
|
||||
for (const name of Object.keys(settings.value.commands)) {
|
||||
// @ts-ignore
|
||||
const newValue = commandObject.value[name]
|
||||
const newValue = commandObject.value[name];
|
||||
// @ts-ignore
|
||||
if(name in commandObject.value && !Array.isArray(newValue)) {
|
||||
if (name in commandObject.value && !Array.isArray(newValue)) {
|
||||
// @ts-ignore
|
||||
newSettings.commands[name] = newValue
|
||||
.split("\n")
|
||||
.filter((cmd: string) => cmd !== "");
|
||||
.split("\n")
|
||||
.filter((cmd: string) => cmd !== "");
|
||||
} else {
|
||||
// @ts-ignore
|
||||
newSettings.commands[name] = newValue
|
||||
newSettings.commands[name] = newValue;
|
||||
}
|
||||
}
|
||||
newSettings.shell = shellValue.value.split("\n");
|
||||
@ -381,7 +388,7 @@ onMounted(async () => {
|
||||
originalSettings.value = original;
|
||||
settings.value = newSettings;
|
||||
// @ts-ignore
|
||||
shellValue.value = newSettings.shell.join("\n")
|
||||
shellValue.value = newSettings.shell.join("\n");
|
||||
} catch (e) {
|
||||
error.value = e;
|
||||
} finally {
|
||||
|
||||
@ -5,26 +5,19 @@
|
||||
"target": "ESNext",
|
||||
"useDefineForClassFields": true,
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "Node",
|
||||
"moduleResolution": "Node10",
|
||||
"strict": true,
|
||||
"jsx": "preserve",
|
||||
"sourceMap": true,
|
||||
"outDir": "../dist/frontend",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"esModuleInterop": true,
|
||||
"lib": ["ESNext", "DOM"],
|
||||
"skipLibCheck": true,
|
||||
"types": ["vite/client"],
|
||||
"typeRoots": ["./node_modules/@types", "./some-custom-lib"],
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": [
|
||||
"./**/*.ts",
|
||||
"src/**/*.d.ts",
|
||||
"src/**/*.vue",
|
||||
],
|
||||
"include": ["src/**/*.ts", "src/**/*.vue", "src/i18n/index.ts.bak"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user