Migration to Vite 4 (initial commit)

This commit is contained in:
Kloon ImKloon 2023-08-12 10:16:11 +02:00
parent ff1e0b8185
commit 17d80aa9ca
No known key found for this signature in database
GPG Key ID: CCF1C86A995C5B6A
36 changed files with 4011 additions and 25856 deletions

20
frontend/.eslintrc.json Normal file
View File

@ -0,0 +1,20 @@
{
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended",
"@vue/eslint-config-prettier"
],
"rules": {
"vue/multi-word-component-names": "warn",
"vue/no-reserved-component-names": "warn",
"vue/no-mutating-props": "warn"
},
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
}
}

2
frontend/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
dist/*
node_modules

View File

@ -0,0 +1,3 @@
{
"trailingComma": "es5"
}

View File

@ -1,3 +0,0 @@
module.exports = {
presets: ["@vue/app"],
};

View File

@ -1,4 +0,0 @@
# Ignore everything in this directory
*
# Except this file
!.gitignore

194
frontend/index.html Normal file
View File

@ -0,0 +1,194 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, user-scalable=no"
/>
[{[ if .ReCaptcha -]}]
<script src="[{[ .ReCaptchaHost ]}]/recaptcha/api.js?render=explicit"></script>
[{[ end ]}]
<title>
[{[ if .Name -]}][{[ .Name ]}][{[ else ]}]File Browser[{[ end ]}]
</title>
<link
rel="icon"
type="image/png"
sizes="32x32"
href="[{[ .StaticURL ]}]/img/icons/favicon-32x32.png"
/>
<link
rel="icon"
type="image/png"
sizes="16x16"
href="[{[ .StaticURL ]}]/img/icons/favicon-16x16.png"
/>
<!-- Add to home screen for Android and modern mobile browsers -->
<link
rel="manifest"
id="manifestPlaceholder"
crossorigin="use-credentials"
/>
<meta
name="theme-color"
content="[{[ if .Color -]}][{[ .Color ]}][{[ else ]}]#2979ff[{[ end ]}]"
/>
<!-- Add to home screen for Safari on iOS/iPadOS -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="apple-mobile-web-app-title" content="assets" />
<link
rel="apple-touch-icon"
href="[{[ .StaticURL ]}]/img/icons/apple-touch-icon.png"
/>
<!-- Add to home screen for Windows -->
<meta
name="msapplication-TileImage"
content="[{[ .StaticURL ]}]/img/icons/mstile-144x144.png"
/>
<meta
name="msapplication-TileColor"
content="[{[ if .Color -]}][{[ .Color ]}][{[ else ]}]#2979ff[{[ end ]}]"
/>
<!-- Inject Some Variables and generate the manifest json -->
<script>
<!-- We can load JSON directly -->
window.FileBrowser = [{[ .Json ]}];
window.__appendStaticUrl = (filename) => {
return `$(window.FileBrowser.StaticURL)/$(filename)`;
}
var fullStaticURL = window.location.origin + window.FileBrowser.StaticURL;
var dynamicManifest = {
name: window.FileBrowser.Name || "File Browser",
short_name: window.FileBrowser.Name || "File Browser",
icons: [
{
src: fullStaticURL + "/img/icons/android-chrome-192x192.png",
sizes: "192x192",
type: "image/png",
},
{
src: fullStaticURL + "/img/icons/android-chrome-512x512.png",
sizes: "512x512",
type: "image/png",
},
],
start_url: window.location.origin + window.FileBrowser.BaseURL,
display: "standalone",
background_color: "#ffffff",
theme_color: window.FileBrowser.Color || "#455a64",
};
const stringManifest = JSON.stringify(dynamicManifest);
const blob = new Blob([stringManifest], { type: "application/json" });
const manifestURL = URL.createObjectURL(blob);
document
.querySelector("#manifestPlaceholder")
.setAttribute("href", manifestURL);
</script>
<style>
#loading {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: #fff;
z-index: 9999;
transition: 0.1s ease opacity;
-webkit-transition: 0.1s ease opacity;
}
#loading.done {
opacity: 0;
}
#loading .spinner {
width: 70px;
text-align: center;
position: fixed;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
}
#loading .spinner > div {
width: 18px;
height: 18px;
background-color: #333;
border-radius: 100%;
display: inline-block;
-webkit-animation: sk-bouncedelay 1.4s infinite ease-in-out both;
animation: sk-bouncedelay 1.4s infinite ease-in-out both;
}
#loading .spinner .bounce1 {
-webkit-animation-delay: -0.32s;
animation-delay: -0.32s;
}
#loading .spinner .bounce2 {
-webkit-animation-delay: -0.16s;
animation-delay: -0.16s;
}
@-webkit-keyframes sk-bouncedelay {
0%,
80%,
100% {
-webkit-transform: scale(0);
}
40% {
-webkit-transform: scale(1);
}
}
@keyframes sk-bouncedelay {
0%,
80%,
100% {
-webkit-transform: scale(0);
transform: scale(0);
}
40% {
-webkit-transform: scale(1);
transform: scale(1);
}
}
</style>
</head>
<body>
<div id="app"></div>
<div id="loading">
<div class="spinner">
<div class="bounce1"></div>
<div class="bounce2"></div>
<div class="bounce3"></div>
</div>
</div>
<script type="module" src="/src/main.js"></script>
[{[ if .Theme -]}]
<link
rel="stylesheet"
href="[{[ .StaticURL ]}]/themes/[{[ .Theme ]}].css"
/>
[{[ end ]}] [{[ if .CSS -]}]
<link rel="stylesheet" href="[{[ .StaticURL ]}]/custom.css" />
[{[ end ]}]
</body>
</html>

29108
frontend/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -2,71 +2,57 @@
"name": "filebrowser-frontend", "name": "filebrowser-frontend",
"version": "2.0.0", "version": "2.0.0",
"private": true, "private": true,
"type": "module",
"scripts": { "scripts": {
"serve": "vue-cli-service serve", "dev": "vite dev",
"build": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitignore' -exec rm -r {} + && vue-cli-service build --no-clean", "serve": "vite serve",
"lint": "npx vue-cli-service lint --no-fix --max-warnings=0", "build": "rimraf dist && vite build",
"fix": "npx vue-cli-service lint", "watch": "rimraf dist && vite build --watch",
"watch": "find ./dist -maxdepth 1 -mindepth 1 ! -name '.gitignore' -exec rm -r {} + && vue-cli-service build --watch --no-clean" "lint": "eslint --ext .vue,.js src/",
"lint:fix": "eslint --ext .vue,.js src/ --fix",
"format": "prettier --write ."
}, },
"dependencies": { "dependencies": {
"ace-builds": "^1.4.7", "ace-builds": "^1.23.4",
"clipboard": "^2.0.4", "clipboard": "^2.0.11",
"core-js": "^3.9.1", "core-js": "^3.32.0",
"css-vars-ponyfill": "^2.4.3", "css-vars-ponyfill": "^2.4.8",
"js-base64": "^2.5.1", "filesize": "^10.0.8",
"js-base64": "^3.7.5",
"lodash.clonedeep": "^4.5.0", "lodash.clonedeep": "^4.5.0",
"lodash.throttle": "^4.1.1", "lodash.throttle": "^4.1.1",
"material-icons": "^1.10.5", "material-icons": "^1.13.9",
"moment": "^2.29.4", "moment": "^2.29.4",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"noty": "^3.2.0-beta", "noty": "^3.2.0-beta",
"pretty-bytes": "^6.0.0", "pretty-bytes": "^6.1.1",
"qrcode.vue": "^1.7.0", "qrcode.vue": "^1.7.0",
"tus-js-client": "^3.1.0", "tus-js-client": "^3.1.1",
"utif": "^3.1.0", "utif": "^3.1.0",
"vue": "^2.6.10", "vue": "^2.7.14",
"vue-async-computed": "^3.9.0", "vue-async-computed": "^3.9.0",
"vue-i18n": "^8.15.3", "vue-i18n": "^8.28.2",
"vue-lazyload": "^1.3.3", "vue-lazyload": "^1.3.5",
"vue-router": "^3.1.3", "vue-router": "^3.6.5",
"vue-simple-progress": "^1.1.1", "vue-simple-progress": "^1.1.1",
"vuex": "^3.1.2", "vuex": "^3.6.2",
"vuex-router-sync": "^5.0.0", "vuex-router-sync": "^5.0.0",
"whatwg-fetch": "^3.6.2" "whatwg-fetch": "^3.6.17"
}, },
"devDependencies": { "devDependencies": {
"@vue/cli-plugin-babel": "^4.1.2", "@vitejs/plugin-legacy": "^4.1.1",
"@vue/cli-plugin-eslint": "~4.5.0", "@vitejs/plugin-vue2": "^2.2.0",
"@vue/cli-service": "^4.1.2", "@vue/eslint-config-prettier": "^8.0.0",
"@vue/eslint-config-prettier": "^6.0.0", "autoprefixer": "^10.4.14",
"babel-eslint": "^10.1.0", "eslint": "^8.46.0",
"compression-webpack-plugin": "^6.0.3", "eslint-plugin-prettier": "^5.0.0",
"eslint": "^6.7.2", "eslint-plugin-vue": "^9.16.1",
"eslint-plugin-prettier": "^3.3.1", "jsdom": "^22.1.0",
"eslint-plugin-vue": "^6.2.2", "postcss": "^8.4.27",
"prettier": "^2.2.1", "prettier": "^3.0.1",
"vue-template-compiler": "^2.6.10" "terser": "^5.19.2",
}, "vite": "^4.4.9",
"eslintConfig": { "vite-plugin-compression2": "^0.10.3"
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended",
"@vue/prettier"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"postcss": {
"plugins": {
"autoprefixer": {}
}
}, },
"browserslist": [ "browserslist": [
"> 1%", "> 1%",

View File

@ -0,0 +1,5 @@
module.exports = {
plugins: {
autoprefixer: {},
},
};

View File

@ -6,7 +6,7 @@
<script> <script>
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
__webpack_public_path__ = window.FileBrowser.StaticURL + "/"; // __webpack_public_path__ = window.FileBrowser.StaticURL + "/";
export default { export default {
name: "app", name: "app",

View File

@ -37,7 +37,7 @@
<script> <script>
import { enableThumbs } from "@/utils/constants"; import { enableThumbs } from "@/utils/constants";
import { mapMutations, mapGetters, mapState } from "vuex"; import { mapMutations, mapGetters, mapState } from "vuex";
import filesize from "filesize"; import { filesize } from "filesize";
import moment from "moment"; import moment from "moment";
import { files as api } from "@/api"; import { files as api } from "@/api";
import * as upload from "@/utils/upload"; import * as upload from "@/utils/upload";

View File

@ -34,7 +34,7 @@
<script> <script>
import { logoURL } from "@/utils/constants"; import { logoURL } from "@/utils/constants";
import Action from "@/components/header/Action"; import Action from "@/components/header/Action.vue";
export default { export default {
name: "header-bar", name: "header-bar",

View File

@ -32,7 +32,7 @@
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import FileList from "./FileList"; import FileList from "./FileList.vue";
import { files as api } from "@/api"; import { files as api } from "@/api";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";
import * as upload from "@/utils/upload"; import * as upload from "@/utils/upload";

View File

@ -81,7 +81,7 @@
<script> <script>
import { mapState, mapGetters } from "vuex"; import { mapState, mapGetters } from "vuex";
import filesize from "filesize"; import { filesize } from "filesize";
import moment from "moment"; import moment from "moment";
import { files as api } from "@/api"; import { files as api } from "@/api";

View File

@ -32,7 +32,7 @@
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import FileList from "./FileList"; import FileList from "./FileList.vue";
import { files as api } from "@/api"; import { files as api } from "@/api";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";
import * as upload from "@/utils/upload"; import * as upload from "@/utils/upload";

View File

@ -6,20 +6,20 @@
</template> </template>
<script> <script>
import Help from "./Help"; import Help from "./Help.vue";
import Info from "./Info"; import Info from "./Info.vue";
import Delete from "./Delete"; import Delete from "./Delete.vue";
import Rename from "./Rename"; import Rename from "./Rename.vue";
import Download from "./Download"; import Download from "./Download.vue";
import Move from "./Move"; import Move from "./Move.vue";
import Copy from "./Copy"; import Copy from "./Copy.vue";
import NewFile from "./NewFile"; import NewFile from "./NewFile.vue";
import NewDir from "./NewDir"; import NewDir from "./NewDir.vue";
import Replace from "./Replace"; import Replace from "./Replace.vue";
import ReplaceRename from "./ReplaceRename"; import ReplaceRename from "./ReplaceRename.vue";
import Share from "./Share"; import Share from "./Share.vue";
import Upload from "./Upload"; import Upload from "./Upload.vue";
import ShareDelete from "./ShareDelete"; import ShareDelete from "./ShareDelete.vue";
import { mapState } from "vuex"; import { mapState } from "vuex";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";

View File

@ -67,10 +67,10 @@
</template> </template>
<script> <script>
import Languages from "./Languages"; import Languages from "./Languages.vue";
import Rules from "./Rules"; import Rules from "./Rules.vue";
import Permissions from "./Permissions"; import Permissions from "./Permissions.vue";
import Commands from "./Commands"; import Commands from "./Commands.vue";
import { enableExec } from "@/utils/constants"; import { enableExec } from "@/utils/constants";
export default { export default {

View File

@ -1,172 +1,241 @@
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../assets/fonts/roboto/normal-cyrillic-ext.woff2) format('woff2'); src:
local("Roboto"),
local("Roboto-Regular"),
url(../assets/fonts/roboto/normal-cyrillic-ext.woff2) format("woff2");
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../assets/fonts/roboto/normal-cyrillic.woff2) format('woff2'); src:
local("Roboto"),
local("Roboto-Regular"),
url(../assets/fonts/roboto/normal-cyrillic.woff2) format("woff2");
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../assets/fonts/roboto/normal-greek-ext.woff2) format('woff2'); src:
local("Roboto"),
local("Roboto-Regular"),
url(../assets/fonts/roboto/normal-greek-ext.woff2) format("woff2");
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../assets/fonts/roboto/normal-greek.woff2) format('woff2'); src:
local("Roboto"),
local("Roboto-Regular"),
url(../assets/fonts/roboto/normal-greek.woff2) format("woff2");
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../assets/fonts/roboto/normal-vietnamese.woff2) format('woff2'); src:
local("Roboto"),
local("Roboto-Regular"),
url(../assets/fonts/roboto/normal-vietnamese.woff2) format("woff2");
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../assets/fonts/roboto/normal-latin-ext.woff2) format('woff2'); src:
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; local("Roboto"),
local("Roboto-Regular"),
url(../assets/fonts/roboto/normal-latin-ext.woff2) format("woff2");
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F,
U+A720-A7FF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 400; font-weight: 400;
src: local('Roboto'), local('Roboto-Regular'), url(../assets/fonts/roboto/normal-latin.woff2) format('woff2'); src:
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; local("Roboto"),
local("Roboto-Regular"),
url(../assets/fonts/roboto/normal-latin.woff2) format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../assets/fonts/roboto/medium-cyrillic-ext.woff2) format('woff2'); src:
local("Roboto Medium"),
local("Roboto-Medium"),
url(../assets/fonts/roboto/medium-cyrillic-ext.woff2) format("woff2");
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../assets/fonts/roboto/medium-cyrillic.woff2) format('woff2'); src:
local("Roboto Medium"),
local("Roboto-Medium"),
url(../assets/fonts/roboto/medium-cyrillic.woff2) format("woff2");
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../assets/fonts/roboto/medium-greek-ext.woff2) format('woff2'); src:
local("Roboto Medium"),
local("Roboto-Medium"),
url(../assets/fonts/roboto/medium-greek-ext.woff2) format("woff2");
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../assets/fonts/roboto/medium-greek.woff2) format('woff2'); src:
local("Roboto Medium"),
local("Roboto-Medium"),
url(../assets/fonts/roboto/medium-greek.woff2) format("woff2");
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../assets/fonts/roboto/medium-vietnamese.woff2) format('woff2'); src:
local("Roboto Medium"),
local("Roboto-Medium"),
url(../assets/fonts/roboto/medium-vietnamese.woff2) format("woff2");
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../assets/fonts/roboto/medium-latin-ext.woff2) format('woff2'); src:
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; local("Roboto Medium"),
local("Roboto-Medium"),
url(../assets/fonts/roboto/medium-latin-ext.woff2) format("woff2");
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F,
U+A720-A7FF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 500; font-weight: 500;
src: local('Roboto Medium'), local('Roboto-Medium'), url(../assets/fonts/roboto/medium-latin.woff2) format('woff2'); src:
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; local("Roboto Medium"),
local("Roboto-Medium"),
url(../assets/fonts/roboto/medium-latin.woff2) format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-cyrillic-ext.woff2) format('woff2'); src:
local("Roboto Bold"),
local("Roboto-Bold"),
url(../assets/fonts/roboto/bold-cyrillic-ext.woff2) format("woff2");
unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F; unicode-range: U+0460-052F, U+20B4, U+2DE0-2DFF, U+A640-A69F;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-cyrillic.woff2) format('woff2'); src:
local("Roboto Bold"),
local("Roboto-Bold"),
url(../assets/fonts/roboto/bold-cyrillic.woff2) format("woff2");
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-greek-ext.woff2) format('woff2'); src:
local("Roboto Bold"),
local("Roboto-Bold"),
url(../assets/fonts/roboto/bold-greek-ext.woff2) format("woff2");
unicode-range: U+1F00-1FFF; unicode-range: U+1F00-1FFF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-greek.woff2) format('woff2'); src:
local("Roboto Bold"),
local("Roboto-Bold"),
url(../assets/fonts/roboto/bold-greek.woff2) format("woff2");
unicode-range: U+0370-03FF; unicode-range: U+0370-03FF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-vietnamese.woff2) format('woff2'); src:
local("Roboto Bold"),
local("Roboto-Bold"),
url(../assets/fonts/roboto/bold-vietnamese.woff2) format("woff2");
unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB; unicode-range: U+0102-0103, U+1EA0-1EF9, U+20AB;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-latin-ext.woff2) format('woff2'); src:
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F, U+A720-A7FF; local("Roboto Bold"),
local("Roboto-Bold"),
url(../assets/fonts/roboto/bold-latin-ext.woff2) format("woff2");
unicode-range: U+0100-024F, U+1E00-1EFF, U+20A0-20AB, U+20AD-20CF, U+2C60-2C7F,
U+A720-A7FF;
} }
@font-face { @font-face {
font-family: 'Roboto'; font-family: "Roboto";
font-style: normal; font-style: normal;
font-weight: 700; font-weight: 700;
src: local('Roboto Bold'), local('Roboto-Bold'), url(../assets/fonts/roboto/bold-latin.woff2) format('woff2'); src:
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000; local("Roboto Bold"),
local("Roboto-Bold"),
url(../assets/fonts/roboto/bold-latin.woff2) format("woff2");
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02C6, U+02DA, U+02DC,
U+2000-206F, U+2074, U+20AC, U+2212, U+2215, U+E0FF, U+EFFD, U+F000;
} }
@import '~material-icons/iconfont/filled.css'; @import "~material-icons/iconfont/filled.css";
.material-icons { .material-icons {
font-size: 1.5rem; font-size: 1.5rem;

View File

@ -1,6 +1,6 @@
@import "~normalize.css/normalize.css"; @import "normalize.css/normalize.css";
@import "~noty/lib/noty.css"; @import "noty/lib/noty.css";
@import "~noty/lib/themes/mint.css"; @import "noty/lib/themes/mint.css";
@import "./_variables.css"; @import "./_variables.css";
@import "./_buttons.css"; @import "./_buttons.css";
@import "./_inputs.css"; @import "./_inputs.css";
@ -27,9 +27,9 @@ main .spinner {
} }
main .spinner > div { main .spinner > div {
width: .8em; width: 0.8em;
height: .8em; height: 0.8em;
margin: 0 .1em; margin: 0 0.1em;
font-size: 1em; font-size: 1em;
background-color: rgba(0, 0, 0, 0.3); background-color: rgba(0, 0, 0, 0.3);
border-radius: 100%; border-radius: 100%;
@ -71,7 +71,7 @@ main .spinner .bounce2 {
transition: 0.2s ease all; transition: 0.2s ease all;
border: 0; border: 0;
margin: 0; margin: 0;
color: #546E7A; color: #546e7a;
border-radius: 50%; border-radius: 50%;
background: transparent; background: transparent;
padding: 0; padding: 0;
@ -88,12 +88,12 @@ main .spinner .bounce2 {
.action i { .action i {
padding: 0.4em; padding: 0.4em;
transition: .1s ease-in-out all; transition: 0.1s ease-in-out all;
border-radius: 50%; border-radius: 50%;
} }
.action:hover { .action:hover {
background-color: rgba(0, 0, 0, .1); background-color: rgba(0, 0, 0, 0.1);
} }
.action ul { .action ul {
@ -109,8 +109,8 @@ main .spinner .bounce2 {
.action ul li { .action ul li {
line-height: 1; line-height: 1;
padding: .7em; padding: 0.7em;
transition: .1s ease background-color; transition: 0.1s ease background-color;
} }
.action ul li:hover { .action ul li:hover {
@ -139,7 +139,7 @@ main .spinner .bounce2 {
background: var(--blue); background: var(--blue);
color: #fff; color: #fff;
border-radius: 50%; border-radius: 50%;
font-size: .75em; font-size: 0.75em;
width: 1.8em; width: 1.8em;
height: 1.8em; height: 1.8em;
text-align: center; text-align: center;
@ -148,7 +148,6 @@ main .spinner .bounce2 {
border: 2px solid white; border: 2px solid white;
} }
/* PREVIEWER */ /* PREVIEWER */
#previewer { #previewer {
@ -179,7 +178,7 @@ main .spinner .bounce2 {
} }
#previewer header .action:hover { #previewer header .action:hover {
background-color: rgba(255, 255, 255, 0.3) background-color: rgba(255, 255, 255, 0.3);
} }
#previewer header .action span { #previewer header .action span {
@ -220,14 +219,14 @@ main .spinner .bounce2 {
} }
#previewer .preview .info .title i { #previewer .preview .info .title i {
display: block; display: block;
margin-bottom: .1em; margin-bottom: 0.1em;
font-size: 4em; font-size: 4em;
} }
#previewer .preview .info .button { #previewer .preview .info .button {
display: inline-block; display: inline-block;
} }
#previewer .preview .info .button:hover { #previewer .preview .info .button:hover {
background-color: rgba(255, 255, 255, 0.2) background-color: rgba(255, 255, 255, 0.2);
} }
#previewer .preview .info .button i { #previewer .preview .info .button i {
display: block; display: block;
@ -241,15 +240,15 @@ main .spinner .bounce2 {
} }
#previewer h2.message { #previewer h2.message {
color: rgba(255, 255, 255, 0.5) color: rgba(255, 255, 255, 0.5);
} }
#previewer>button { #previewer > button {
margin: 0; margin: 0;
position: fixed; position: fixed;
top: calc(50% + 1.85em); top: calc(50% + 1.85em);
transform: translateY(-50%); transform: translateY(-50%);
background-color: rgba(80, 80, 80, .5); background-color: rgba(80, 80, 80, 0.5);
color: white; color: white;
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
@ -259,20 +258,20 @@ main .spinner .bounce2 {
transition: 0.2s ease all; transition: 0.2s ease all;
} }
#previewer>button.hidden { #previewer > button.hidden {
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
} }
#previewer>button>i { #previewer > button > i {
padding: 0.4em; padding: 0.4em;
} }
#previewer>button:first-of-type { #previewer > button:first-of-type {
left: 0.5em; left: 0.5em;
} }
#previewer>button:last-of-type { #previewer > button:last-of-type {
right: 0.5em; right: 0.5em;
} }
@ -321,7 +320,7 @@ body.rtl .breadcrumbs .chevron {
} }
#editor-container .breadcrumbs span { #editor-container .breadcrumbs span {
font-size: .75rem; font-size: 0.75rem;
} }
#editor-container .breadcrumbs i { #editor-container .breadcrumbs i {
@ -339,7 +338,7 @@ body.rtl .breadcrumbs .chevron {
.noty_buttons button { .noty_buttons button {
background: rgba(0, 0, 0, 0.05); background: rgba(0, 0, 0, 0.05);
border: 1px solid rgba(0,0,0,0.1); border: 1px solid rgba(0, 0, 0, 0.1);
box-shadow: 0 0 0 0; box-shadow: 0 0 0 0;
font-size: 1rem; font-size: 1rem;
} }
@ -356,7 +355,7 @@ body.rtl .breadcrumbs .chevron {
.credits > span { .credits > span {
display: block; display: block;
margin: .3em 0; margin: 0.3em 0;
} }
.credits a, .credits a,
@ -365,7 +364,6 @@ body.rtl .breadcrumbs .chevron {
cursor: pointer; cursor: pointer;
} }
/* * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * *
* ANIMATIONS * * ANIMATIONS *
* * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * */
@ -393,20 +391,20 @@ body.rtl .breadcrumbs .chevron {
.rules > div { .rules > div {
display: flex; display: flex;
align-items: center; align-items: center;
margin: .5rem 0; margin: 0.5rem 0;
} }
.rules input[type="checkbox"] { .rules input[type="checkbox"] {
margin-right: .2rem; margin-right: 0.2rem;
} }
.rules input[type="text"] { .rules input[type="text"] {
border: 1px solid#ddd; border: 1px solid#ddd;
padding: .2rem; padding: 0.2rem;
} }
.rules label { .rules label {
margin-right: .5rem; margin-right: 0.5rem;
} }
.rules button { .rules button {
@ -414,11 +412,11 @@ body.rtl .breadcrumbs .chevron {
} }
.rules button.delete { .rules button.delete {
padding: .2rem .5rem; padding: 0.2rem 0.5rem;
margin-left: .5rem; margin-left: 0.5rem;
} }
@import './mobile.css'; @import "./mobile.css";
/* * * * * * * * * * * * * * * * /* * * * * * * * * * * * * * * *
* RTL overrides * * RTL overrides *

View File

@ -7,7 +7,7 @@ import i18n from "@/i18n";
import Vue from "@/utils/vue"; import Vue from "@/utils/vue";
import { recaptcha, loginPage } from "@/utils/constants"; import { recaptcha, loginPage } from "@/utils/constants";
import { login, validateLogin } from "@/utils/auth"; import { login, validateLogin } from "@/utils/auth";
import App from "@/App"; import App from "@/App.vue";
cssVars(); cssVars();

View File

@ -1,16 +1,16 @@
import Vue from "vue"; import Vue from "vue";
import Router from "vue-router"; import Router from "vue-router";
import Login from "@/views/Login"; import Login from "@/views/Login.vue";
import Layout from "@/views/Layout"; import Layout from "@/views/Layout.vue";
import Files from "@/views/Files"; import Files from "@/views/Files.vue";
import Share from "@/views/Share"; import Share from "@/views/Share.vue";
import Users from "@/views/settings/Users"; import Users from "@/views/settings/Users.vue";
import User from "@/views/settings/User"; import User from "@/views/settings/User.vue";
import Settings from "@/views/Settings"; import Settings from "@/views/Settings.vue";
import GlobalSettings from "@/views/settings/Global"; import GlobalSettings from "@/views/settings/Global.vue";
import ProfileSettings from "@/views/settings/Profile"; import ProfileSettings from "@/views/settings/Profile.vue";
import Shares from "@/views/settings/Shares"; import Shares from "@/views/settings/Shares.vue";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors.vue";
import store from "@/store"; import store from "@/store";
import { baseURL, name } from "@/utils/constants"; import { baseURL, name } from "@/utils/constants";
import i18n, { rtlLanguages } from "@/i18n"; import i18n, { rtlLanguages } from "@/i18n";

View File

@ -10,7 +10,7 @@
</template> </template>
<script> <script>
import HeaderBar from "@/components/header/HeaderBar"; import HeaderBar from "@/components/header/HeaderBar.vue";
const errors = { const errors = {
0: { 0: {

View File

@ -23,11 +23,11 @@
import { files as api } from "@/api"; import { files as api } from "@/api";
import { mapState, mapMutations } from "vuex"; import { mapState, mapMutations } from "vuex";
import HeaderBar from "@/components/header/HeaderBar"; import HeaderBar from "@/components/header/HeaderBar.vue";
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs.vue";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors.vue";
import Preview from "@/views/files/Preview"; import Preview from "@/views/files/Preview.vue";
import Listing from "@/views/files/Listing"; import Listing from "@/views/files/Listing.vue";
function clean(path) { function clean(path) {
return path.endsWith("/") ? path.slice(0, -1) : path; return path.endsWith("/") ? path.slice(0, -1) : path;
@ -41,7 +41,7 @@ export default {
Errors, Errors,
Preview, Preview,
Listing, Listing,
Editor: () => import("@/views/files/Editor"), Editor: () => import("@/views/files/Editor.vue"),
}, },
data: function () { data: function () {
return { return {

View File

@ -15,10 +15,10 @@
<script> <script>
import { mapState, mapGetters } from "vuex"; import { mapState, mapGetters } from "vuex";
import Sidebar from "@/components/Sidebar"; import Sidebar from "@/components/Sidebar.vue";
import Prompts from "@/components/prompts/Prompts"; import Prompts from "@/components/prompts/Prompts.vue";
import Shell from "@/components/Shell"; import Shell from "@/components/Shell.vue";
import UploadFiles from "../components/prompts/UploadFiles"; import UploadFiles from "../components/prompts/UploadFiles.vue";
import { enableExec } from "@/utils/constants"; import { enableExec } from "@/utils/constants";
export default { export default {

View File

@ -52,7 +52,7 @@
<script> <script>
import { mapState } from "vuex"; import { mapState } from "vuex";
import HeaderBar from "@/components/header/HeaderBar"; import HeaderBar from "@/components/header/HeaderBar.vue";
export default { export default {
name: "settings", name: "settings",

View File

@ -182,15 +182,15 @@
<script> <script>
import { mapState, mapMutations, mapGetters } from "vuex"; import { mapState, mapMutations, mapGetters } from "vuex";
import { pub as api } from "@/api"; import { pub as api } from "@/api";
import filesize from "filesize"; import { filesize } from "filesize";
import moment from "moment"; import moment from "moment";
import HeaderBar from "@/components/header/HeaderBar"; import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action"; import Action from "@/components/header/Action.vue";
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs.vue";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors.vue";
import QrcodeVue from "qrcode.vue"; import QrcodeVue from "qrcode.vue";
import Item from "@/components/files/ListingItem"; import Item from "@/components/files/ListingItem.vue";
import Clipboard from "clipboard"; import Clipboard from "clipboard";
export default { export default {

View File

@ -28,11 +28,10 @@ import url from "@/utils/url";
import ace from "ace-builds/src-min-noconflict/ace.js"; import ace from "ace-builds/src-min-noconflict/ace.js";
import modelist from "ace-builds/src-min-noconflict/ext-modelist.js"; import modelist from "ace-builds/src-min-noconflict/ext-modelist.js";
import "ace-builds/webpack-resolver";
import HeaderBar from "@/components/header/HeaderBar"; import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action"; import Action from "@/components/header/Action.vue";
import Breadcrumbs from "@/components/Breadcrumbs"; import Breadcrumbs from "@/components/Breadcrumbs.vue";
export default { export default {
name: "editor", name: "editor",

View File

@ -1,7 +1,8 @@
<template> <template>
<div> <div>
<header-bar showMenu showLogo> <header-bar showMenu showLogo>
<search /> <title /> <search />
<title />
<action <action
class="search-button" class="search-button"
icon="search" icon="search"
@ -274,10 +275,10 @@ import * as upload from "@/utils/upload";
import css from "@/utils/css"; import css from "@/utils/css";
import throttle from "lodash.throttle"; import throttle from "lodash.throttle";
import HeaderBar from "@/components/header/HeaderBar"; import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action"; import Action from "@/components/header/Action.vue";
import Search from "@/components/Search"; import Search from "@/components/Search.vue";
import Item from "@/components/files/ListingItem"; import Item from "@/components/files/ListingItem.vue";
export default { export default {
name: "listing", name: "listing",

View File

@ -148,9 +148,9 @@ import { files as api } from "@/api";
import { resizePreview } from "@/utils/constants"; import { resizePreview } from "@/utils/constants";
import url from "@/utils/url"; import url from "@/utils/url";
import throttle from "lodash.throttle"; import throttle from "lodash.throttle";
import HeaderBar from "@/components/header/HeaderBar"; import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action"; import Action from "@/components/header/Action.vue";
import ExtendedImage from "@/components/files/ExtendedImage"; import ExtendedImage from "@/components/files/ExtendedImage.vue";
const mediaTypes = ["image", "video", "audio", "blob"]; const mediaTypes = ["image", "video", "audio", "blob"];

View File

@ -223,10 +223,10 @@
import { mapState, mapMutations } from "vuex"; import { mapState, mapMutations } from "vuex";
import { settings as api } from "@/api"; import { settings as api } from "@/api";
import { enableExec } from "@/utils/constants"; import { enableExec } from "@/utils/constants";
import UserForm from "@/components/settings/UserForm"; import UserForm from "@/components/settings/UserForm.vue";
import Rules from "@/components/settings/Rules"; import Rules from "@/components/settings/Rules.vue";
import Themes from "@/components/settings/Themes"; import Themes from "@/components/settings/Themes.vue";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors.vue";
export default { export default {
name: "settings", name: "settings",

View File

@ -74,7 +74,7 @@
<script> <script>
import { mapState, mapMutations } from "vuex"; import { mapState, mapMutations } from "vuex";
import { users as api } from "@/api"; import { users as api } from "@/api";
import Languages from "@/components/settings/Languages"; import Languages from "@/components/settings/Languages.vue";
import i18n, { rtlLanguages } from "@/i18n"; import i18n, { rtlLanguages } from "@/i18n";
export default { export default {

View File

@ -65,7 +65,7 @@ import { share as api, users } from "@/api";
import { mapState, mapMutations } from "vuex"; import { mapState, mapMutations } from "vuex";
import moment from "moment"; import moment from "moment";
import Clipboard from "clipboard"; import Clipboard from "clipboard";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors.vue";
export default { export default {
name: "shares", name: "shares",

View File

@ -63,8 +63,8 @@
<script> <script>
import { mapState, mapMutations } from "vuex"; import { mapState, mapMutations } from "vuex";
import { users as api, settings } from "@/api"; import { users as api, settings } from "@/api";
import UserForm from "@/components/settings/UserForm"; import UserForm from "@/components/settings/UserForm.vue";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors.vue";
import deepClone from "lodash.clonedeep"; import deepClone from "lodash.clonedeep";
export default { export default {

View File

@ -44,7 +44,7 @@
<script> <script>
import { mapState, mapMutations } from "vuex"; import { mapState, mapMutations } from "vuex";
import { users as api } from "@/api"; import { users as api } from "@/api";
import Errors from "@/views/Errors"; import Errors from "@/views/Errors.vue";
export default { export default {
name: "users", name: "users",

42
frontend/vite.config.js Normal file
View File

@ -0,0 +1,42 @@
import { fileURLToPath, URL } from "node:url";
import { defineConfig } from "vite";
import legacy from "@vitejs/plugin-legacy";
import vue2 from "@vitejs/plugin-vue2";
import { compression } from "vite-plugin-compression2";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue2(),
legacy({
targets: ["ie >= 11"],
additionalLegacyPolyfills: ["regenerator-runtime/runtime"],
}),
compression({ include: /\.js$/i, deleteOriginalAssets: true }),
],
resolve: {
alias: {
"@/": fileURLToPath(new URL("./src/", import.meta.url)),
},
},
base: "",
experimental: {
renderBuiltUrl(filename, { hostType }) {
if (hostType === "js") {
return { runtime: `window.__appendStaticUrl("${filename}")` };
// } else if (hostType === "css") {
// return `'[{[ .StaticURL ]}]/${filename}'`;
} else if (hostType === "html") {
return `[{[ .StaticURL ]}]/${filename}`;
// return {
// runtime: `window.__appendStaticUrl(${JSON.stringify(filename)})`,
// };
// if (hostType === "js") {
// return { runtime: `window.__toCdnUrl(${JSON.stringify(filename)})` };
} else {
return { relative: true };
}
},
},
});

View File

@ -1,15 +0,0 @@
const CompressionPlugin = require("compression-webpack-plugin");
module.exports = {
runtimeCompiler: true,
publicPath: "[{[ .StaticURL ]}]",
parallel: 2,
configureWebpack: {
plugins: [
new CompressionPlugin({
include: /\.js$/,
deleteOriginalAssets: true,
}),
],
},
};