Migration to vue3 continued

Replace moment with dayjs
Fix some routing issues
Fix some vuex store leftovers
This commit is contained in:
Kloon ImKloon 2023-08-30 17:47:22 +02:00
parent 3413de8b52
commit 05d011f586
No known key found for this signature in database
GPG Key ID: CCF1C86A995C5B6A
31 changed files with 220 additions and 155 deletions

View File

@ -13,12 +13,11 @@
"ace-builds": "^1.24.1",
"clipboard": "^2.0.11",
"core-js": "^3.32.1",
"css-vars-ponyfill": "^2.4.8",
"dayjs": "^1.11.9",
"filesize": "^10.0.12",
"js-base64": "^3.7.5",
"jwt-decode": "^3.1.2",
"lodash.clonedeep": "^4.5.0",
"lodash.throttle": "^4.1.1",
"lodash-es": "^4.17.21",
"material-icons": "^1.13.10",
"moment": "^2.29.4",
"normalize.css": "^8.0.1",
@ -32,8 +31,7 @@
"vue-i18n": "^9.2.2",
"vue-lazyload": "^3.0.0",
"vue-router": "^4.2.4",
"vue-simple-progress": "^1.1.1",
"whatwg-fetch": "^3.6.17"
"vue-simple-progress": "^1.1.1"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^0.12.3",
@ -2937,7 +2935,8 @@
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
"dev": true
},
"node_modules/big-integer": {
"version": "1.6.51",
@ -3241,15 +3240,6 @@
"node": ">= 8"
}
},
"node_modules/css-vars-ponyfill": {
"version": "2.4.8",
"resolved": "https://registry.npmjs.org/css-vars-ponyfill/-/css-vars-ponyfill-2.4.8.tgz",
"integrity": "sha512-4/j4AX4htytYHWyHVZ2BFQ+NoCGZEcOH2h4/2mmgE4SkrFg4Xq6tGYR77DtvvUIDsaXuJN+sj41bbgauA0Gfmg==",
"dependencies": {
"balanced-match": "^1.0.2",
"get-css-data": "^2.0.2"
}
},
"node_modules/cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
@ -3298,6 +3288,11 @@
"node": ">=14"
}
},
"node_modules/dayjs": {
"version": "1.11.9",
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.9.tgz",
"integrity": "sha512-QvzAURSbQ0pKdIye2txOzNaHmxtUBXerpY0FJsFXUMKbIZeFm5ht1LS/jFsrncjnmtv8HsG0W2g6c0zUjZWmpA=="
},
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
@ -4094,11 +4089,6 @@
"node": ">=6.9.0"
}
},
"node_modules/get-css-data": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/get-css-data/-/get-css-data-2.1.0.tgz",
"integrity": "sha512-HtPrzGk8aBF9rLeQNuImcXci7YVqsMEKzVflEWaCJu25ehxyDNiZRWoSxqSFUBfma8LERqKo70t/TcaGjIsM9g=="
},
"node_modules/get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@ -4661,6 +4651,11 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
},
"node_modules/lodash._baseiteratee": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/lodash._baseiteratee/-/lodash._baseiteratee-4.7.0.tgz",
@ -4701,11 +4696,6 @@
"lodash._basetostring": "~4.12.0"
}
},
"node_modules/lodash.clonedeep": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
"integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ=="
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
@ -6340,11 +6330,6 @@
"node": ">=12"
}
},
"node_modules/whatwg-fetch": {
"version": "3.6.17",
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.17.tgz",
"integrity": "sha512-c4ghIvG6th0eudYwKZY5keb81wtFz9/WeAHAoy8+r18kcWlitUIrmGFQ2rWEl4UCKUilD3zCLHOIPheHx5ypRQ=="
},
"node_modules/whatwg-mimetype": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz",

View File

@ -18,12 +18,11 @@
"ace-builds": "^1.24.1",
"clipboard": "^2.0.11",
"core-js": "^3.32.1",
"css-vars-ponyfill": "^2.4.8",
"dayjs": "^1.11.9",
"filesize": "^10.0.12",
"js-base64": "^3.7.5",
"jwt-decode": "^3.1.2",
"lodash.clonedeep": "^4.5.0",
"lodash.throttle": "^4.1.1",
"lodash-es": "^4.17.21",
"material-icons": "^1.13.10",
"moment": "^2.29.4",
"normalize.css": "^8.0.1",
@ -37,8 +36,7 @@
"vue-i18n": "^9.2.2",
"vue-lazyload": "^3.0.0",
"vue-router": "^4.2.4",
"vue-simple-progress": "^1.1.1",
"whatwg-fetch": "^3.6.17"
"vue-simple-progress": "^1.1.1"
},
"devDependencies": {
"@intlify/unplugin-vue-i18n": "^0.12.3",

View File

@ -92,6 +92,7 @@ export default {
scrollable: null,
};
},
inject: ["$showError"],
watch: {
show(val, old) {
this.active = val === "search";
@ -162,7 +163,7 @@ export default {
this.closeHovers();
},
keyup(event) {
if (event.keyCode === 27) {
if (event.key === "Escape") {
this.close(event);
return;
}

View File

@ -14,7 +14,7 @@
</div>
</template>
<script>
import throttle from "lodash.throttle";
import throttle from "lodash/throttle";
import UTIF from "utif";
export default {

View File

@ -42,7 +42,7 @@ import { useLayoutStore } from "@/stores/layout";
import { enableThumbs } from "@/utils/constants";
import { filesize } from "filesize";
import moment from "moment";
import dayjs from "dayjs";
import { files as api } from "@/api";
import * as upload from "@/utils/upload";
@ -56,6 +56,7 @@ export default {
touches: 0,
};
},
inject: ["$showError"],
props: [
"name",
"isDir",
@ -111,9 +112,9 @@ export default {
},
humanTime: function () {
if (this.readOnly == undefined && this.user.dateFormat) {
return moment(this.modified).format("L LT");
return dayjs(this.modified).format("L LT");
}
return moment(this.modified).fromNow();
return dayjs(this.modified).fromNow();
},
dragStart: function () {
if (this.selectedCount === 0) {

View File

@ -48,6 +48,7 @@ export default {
dest: null,
};
},
inject: ["$showError"],
computed: {
...mapState(useFileStore, ["req", "selected"]),
...mapWritableState(useFileStore, ["reload"]),

View File

@ -45,6 +45,7 @@ export default {
current: window.location.pathname,
};
},
inject: ["$showError"],
computed: {
...mapState(useAuthStore, ["user"]),
...mapState(useFileStore, ["req"]),

View File

@ -84,11 +84,12 @@ import { mapActions, mapState } from "pinia";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
import { filesize } from "filesize";
import moment from "moment";
import dayjs from "dayjs";
import { files as api } from "@/api";
export default {
name: "info",
inject: ["$showError"],
computed: {
...mapState(useFileStore, [
"req",
@ -111,10 +112,10 @@ export default {
},
humanTime: function () {
if (this.selectedCount === 0) {
return moment(this.req.modified).fromNow();
return dayjs(this.req.modified).fromNow();
}
return moment(this.req.items[this.selected[0]].modified).fromNow();
return dayjs(this.req.items[this.selected[0]].modified).fromNow();
},
modTime: function () {
return new Date(Date.parse(this.req.modified)).toLocaleString();

View File

@ -48,6 +48,7 @@ export default {
dest: null,
};
},
inject: ["$showError"],
computed: mapState(useFileStore, ["req", "selected"]),
methods: {
...mapActions(useLayoutStore, ["showHover", "closeHovers"]),

View File

@ -56,14 +56,12 @@ export default {
let prompt = this.$refs.currentComponent;
// Esc!
if (event.keyCode === 27) {
if (event.key === "Escape") {
event.stopImmediatePropagation();
this.closeHovers();
}
// Enter
if (event.keyCode == 13) {
if (event.key == "Enter") {
switch (this.show) {
case "delete":
prompt.submit();

View File

@ -57,6 +57,7 @@ export default {
created() {
this.name = this.oldName();
},
inject: ["$showError"],
computed: {
...mapState(useFileStore, [
"req",

View File

@ -129,7 +129,7 @@
import { mapActions, mapState } from "pinia";
import { useFileStore } from "@/stores/file";
import { share as api, pub as pub_api } from "@/api";
import moment from "moment";
import dayjs from "dayjs";
import Clipboard from "clipboard";
import { useLayoutStore } from "@/stores/layout";
@ -145,6 +145,7 @@ export default {
listing: true,
};
},
inject: ["$showError"],
computed: {
...mapState(useFileStore, [
"req",
@ -227,7 +228,7 @@ export default {
}
},
humanTime(time) {
return moment(time * 1000).fromNow();
return dayjs(time * 1000).fromNow();
},
buildLink(share) {
return api.getShareURL(share);

View File

@ -1,5 +1,29 @@
import { createI18n } from "vue-i18n";
import("dayjs/locale/ar");
import("dayjs/locale/de");
import("dayjs/locale/en");
import("dayjs/locale/es");
import("dayjs/locale/fr");
import("dayjs/locale/he");
import("dayjs/locale/hu");
import("dayjs/locale/is");
import("dayjs/locale/it");
import("dayjs/locale/ja");
import("dayjs/locale/ko");
import("dayjs/locale/nl-be");
import("dayjs/locale/pl");
import("dayjs/locale/pt-br");
import("dayjs/locale/pt");
import("dayjs/locale/ro");
import("dayjs/locale/ru");
import("dayjs/locale/sk");
import("dayjs/locale/sv");
import("dayjs/locale/tr");
import("dayjs/locale/uk");
import("dayjs/locale/zh-cn");
import("dayjs/locale/zh-tw");
import he from "./he.json";
import hu from "./hu.json";
import ar from "./ar.json";
@ -18,7 +42,7 @@ import ptBR from "./pt-br.json";
import ro from "./ro.json";
import ru from "./ru.json";
import sk from "./sk.json";
import ua from "./ua.json";
import uk from "./uk.json";
import svSE from "./sv-se.json";
import zhCN from "./zh-cn.json";
import zhTW from "./zh-tw.json";
@ -47,21 +71,19 @@ export function detectLocale() {
case /^fr.*/i.test(locale):
locale = "fr";
break;
case /^pt.*/i.test(locale):
locale = "pt";
break;
case /^pt-BR.*/i.test(locale):
locale = "pt-br";
break;
case /^pt.*/i.test(locale):
locale = "pt";
break;
case /^ja.*/i.test(locale):
locale = "ja";
break;
case /^zh-CN/i.test(locale):
locale = "zh-cn";
break;
case /^zh-TW/i.test(locale):
locale = "zh-tw";
break;
case /^zh-CN/i.test(locale):
case /^zh.*/i.test(locale):
locale = "zh-cn";
break;
@ -80,8 +102,13 @@ export function detectLocale() {
case /^sk.*/i.test(locale):
locale = "sk";
break;
case /^uk.*/i.test(locale):
case /^ua.*/i.test(locale):
locale = "ua";
locale = "uk";
break;
case /^sv-SE.*/i.test(locale):
case /^sv.*/i.test(locale):
locale = "sv";
break;
default:
locale = "en";
@ -125,8 +152,8 @@ export const i18n = createI18n({
ru: removeEmpty(ru),
ro: removeEmpty(ro),
sk: removeEmpty(sk),
"sv-se": removeEmpty(svSE),
ua: removeEmpty(ua),
sv: removeEmpty(svSE),
uk: removeEmpty(uk),
"zh-cn": removeEmpty(zhCN),
"zh-tw": removeEmpty(zhTW),
},

View File

@ -1,21 +1,29 @@
import "whatwg-fetch";
import cssVars from "css-vars-ponyfill";
import Noty from "noty";
import { disableExternal } from "@/utils/constants";
import { createApp } from "vue";
import Noty from "noty";
import VueLazyload from "vue-lazyload";
import createPinia from "@/stores";
import router from "@/router";
import i18n from "@/i18n";
import App from "@/App.vue";
cssVars();
// import "core-js/actual/structured-clone";
import dayjs from "dayjs";
import localizedFormat from "dayjs/plugin/localizedFormat";
import relativeTime from "dayjs/plugin/relativeTime";
import duration from "dayjs/plugin/duration";
// register dayjs plugins globally
dayjs.extend(localizedFormat);
dayjs.extend(relativeTime);
dayjs.extend(duration);
const pinia = createPinia(router);
const app = createApp(App);
app.use(VueLazyload);
app.use(i18n);
app.use(pinia);
app.use(router);
@ -37,14 +45,14 @@ app.directive("focus", {
const notyDefault = {
type: "info",
layout: "bottomRight",
layout: "bottomCenter",
timeout: 1000,
progressBar: true,
};
app.provide("$noty", (opts) => {
new Noty(Object.assign({}, notyDefault, opts)).show();
});
// app.provide("$noty", (opts) => {
// new Noty(Object.assign({}, notyDefault, opts)).show();
// });
app.provide("$showSuccess", (message) => {
new Noty(

View File

@ -104,7 +104,7 @@ const routes = [
},
},
{
path: "users/:id(.*)*",
path: "users/:id",
name: "User",
component: User,
meta: {
@ -148,7 +148,7 @@ const routes = [
},
];
async function start() {
async function initialize() {
try {
if (loginPage) {
await validateLogin();
@ -156,7 +156,7 @@ async function start() {
await login("", "", "");
}
} catch (e) {
console.log(e);
console.error(e);
}
if (recaptcha) {
@ -182,9 +182,10 @@ const router = createRouter({
router.beforeResolve(async (to, from, next) => {
let title;
try {
// this should not fail after we finished the migration
title = i18n.global.t(titles[to.name]);
} catch (error) {
title = to.name;
console.error(error);
}
// const title = titles[to.name];
document.title = title + " - " + name;
@ -203,8 +204,9 @@ router.beforeResolve(async (to, from, next) => {
const authStore = useAuthStore();
// this will only be null on first route
if (from.name == null) {
await start();
await initialize();
}
if (to.path.endsWith("/login") && authStore.isLoggedIn) {

View File

@ -1,6 +1,6 @@
import { defineStore } from "pinia";
// import { useAuthPreferencesStore } from "./auth-preferences";
// import { useAuthEmailStore } from "./auth-email";
import dayjs from "dayjs";
import i18n, { detectLocale } from "@/i18n";
export const useAuthStore = defineStore("auth", {
// convert to a function
@ -20,19 +20,20 @@ export const useAuthStore = defineStore("auth", {
return;
}
// const locale = value.locale || i18n.detectLocale();
// moment.locale(locale);
// i18n.default.locale = locale;
const locale = value.locale || detectLocale();
dayjs.locale(locale);
i18n.global.locale.value = locale;
this.user = value;
},
updateUser(value) {
if (typeof value !== "object") return;
for (let field in value) {
// if (field === "locale") {
// moment.locale(value[field]);
// i18n.default.locale = value[field];
// }
if (field === "locale") {
const locale = value[field];
dayjs.locale(locale);
i18n.global.locale.value = locale;
}
this.user[field] = structuredClone(value[field]);
}

View File

@ -1,6 +1,4 @@
import { defineStore } from "pinia";
import { useRouterStore } from "./router";
import { useLayoutStore } from "./layout";
export const useFileStore = defineStore("file", {
// convert to a function
@ -10,17 +8,18 @@ export const useFileStore = defineStore("file", {
reload: false,
selected: [],
multiple: false,
isFiles: false,
}),
getters: {
selectedCount: (state) => state.selected.length,
route: () => {
const routerStore = useRouterStore();
return routerStore.router.currentRoute;
},
isFiles: (state) => {
const layoutStore = useLayoutStore();
return !layoutStore.loading && state.route._value.name === "Files";
},
// route: () => {
// const routerStore = useRouterStore();
// return routerStore.router.currentRoute;
// },
// isFiles: (state) => {
// const layoutStore = useLayoutStore();
// return !layoutStore.loading && state.route._value.name === "Files";
// },
isListing: (state) => {
return state.isFiles && state.req.isDir;
},

View File

@ -1,5 +1,12 @@
import { defineStore } from "pinia";
/**
* @example
* // route: () => {
* // const routerStore = useRouterStore();
* // return routerStore.router.currentRoute;
* // },
*/
export const useRouterStore = defineStore("routerStore", () => {
// can be an empty definition
return {};

View File

@ -1,8 +1,7 @@
import Vue from "vue";
import { defineStore } from "pinia";
import { useFileStore } from "./file";
import { files as api } from "@/api";
import throttle from "lodash.throttle";
import throttle from "lodash/throttle";
import buttons from "@/utils/buttons";
const UPLOADS_LIMIT = 5;
@ -66,7 +65,8 @@ export const useUploadStore = defineStore("upload", {
actions: {
// no context as first argument, use `this` instead
setProgress({ id, loaded }) {
Vue.set(this.progress, id, loaded);
// Vue.set(this.progress, id, loaded);
this.progress[id] = loaded;
},
reset() {
this.id = 0;
@ -81,10 +81,11 @@ export const useUploadStore = defineStore("upload", {
moveJob() {
const item = this.queue[0];
this.queue.shift();
Vue.set(this.uploads, item.id, item);
// Vue.set(this.uploads, item.id, item);
this.uploads[item.id] = item;
},
removeJob(id) {
Vue.delete(this.uploads, id);
// Vue.delete(this.uploads, id);
delete this.uploads[id];
},
upload(item) {
@ -129,7 +130,8 @@ export const useUploadStore = defineStore("upload", {
this.moveJob();
if (item.file.isDir) {
await api.post(item.path).catch(Vue.prototype.$showError);
// TODO: find a way to display notification
await api.post(item.path).catch(console.error);
} else {
let onUpload = throttle(
(event) =>
@ -141,9 +143,10 @@ export const useUploadStore = defineStore("upload", {
{ leading: true, trailing: false }
);
// TODO: find a way to display notification
await api
.post(item.path, item.file, item.overwrite, onUpload)
.catch(Vue.prototype.$showError);
.catch(console.error);
}
this.finishUpload(item);

View File

@ -0,0 +1 @@
export * from "./funcs";

View File

@ -57,6 +57,7 @@ export default {
"reload",
"selected",
"multiple",
"isFiles",
]),
...mapState(useLayoutStore, ["show", "showShell"]),
...mapWritableState(useLayoutStore, ["loading"]),
@ -89,12 +90,14 @@ export default {
},
},
mounted() {
this.isFiles = true;
window.addEventListener("keydown", this.keyEvent);
},
beforeUnmount() {
window.removeEventListener("keydown", this.keyEvent);
},
unmounted() {
this.isFiles = false;
if (this.showShell) {
this.toggleShell();
}
@ -137,8 +140,7 @@ export default {
}
},
keyEvent(event) {
// F1!
if (event.keyCode === 112) {
if (event.key === "F1") {
event.preventDefault();
this.showHover("help");
}

View File

@ -180,7 +180,7 @@
import { mapState, mapActions, mapWritableState } from "pinia";
import { pub as api } from "@/api";
import { filesize } from "filesize";
import moment from "moment";
import dayjs from "dayjs";
import { Base64 } from "js-base64";
import HeaderBar from "@/components/header/HeaderBar.vue";
@ -212,6 +212,7 @@ export default {
token: null,
clip: null,
}),
inject: ["$showSuccess"],
watch: {
$route: function () {
this.showLimit = 100;
@ -260,7 +261,7 @@ export default {
return filesize(this.req.size);
},
humanTime: function () {
return moment(this.req.modified).fromNow();
return dayjs(this.req.modified).fromNow();
},
modTime: function () {
return new Date(Date.parse(this.req.modified)).toLocaleString();
@ -306,8 +307,7 @@ export default {
}
},
keyEvent(event) {
// Esc!
if (event.keyCode === 27) {
if (event.key === "Escape") {
// If we're on a listing, unselect all
// files and folders.
if (this.selectedCount > 0) {

View File

@ -46,6 +46,7 @@ export default {
data: function () {
return {};
},
inject: ["$showError"],
computed: {
...mapState(useAuthStore, ["user"]),
...mapState(useFileStore, ["req"]),

View File

@ -278,7 +278,7 @@ import { users, files as api } from "@/api";
import { enableExec } from "@/utils/constants";
import * as upload from "@/utils/upload";
import css from "@/utils/css";
import throttle from "lodash.throttle";
import throttle from "lodash/throttle";
import { Base64 } from "js-base64";
import HeaderBar from "@/components/header/HeaderBar.vue";
@ -303,6 +303,7 @@ export default {
itemWeight: 0,
};
},
inject: ["$showError"],
computed: {
...mapStores(useClipboardStore),
...mapState(useAuthStore, ["user"]),
@ -456,22 +457,19 @@ export default {
return;
}
// Esc!
if (event.keyCode === 27) {
if (event.key === "Escape") {
// Reset files selection.
this.selected = [];
}
// Del!
if (event.keyCode === 46) {
if (event.key === "Delete") {
if (!this.user.perm.delete || this.selectedCount == 0) return;
// Show delete prompt.
this.showHover("delete");
}
// F2!
if (event.keyCode === 113) {
if (event.key === "F2") {
if (!this.user.perm.rename || this.selectedCount !== 1) return;
// Show rename prompt.

View File

@ -151,7 +151,7 @@ import { useLayoutStore } from "@/stores/layout";
import { files as api } from "@/api";
import { resizePreview } from "@/utils/constants";
import url from "@/utils/url";
import throttle from "lodash.throttle";
import throttle from "lodash/throttle";
import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action.vue";
import ExtendedImage from "@/components/files/ExtendedImage.vue";
@ -180,6 +180,7 @@ export default {
nextRaw: "",
};
},
inject: ["$showError"],
computed: {
...mapState(useAuthStore, ["user", "jwt"]),
...mapState(useFileStore, ["req", "oldReq", "loading"]),

View File

@ -246,6 +246,7 @@ export default {
debounceTimeout: null,
};
},
inject: ["$showError", "$showSuccess"],
computed: {
...mapState(useAuthStore, ["user"]),
...mapWritableState(useLayoutStore, ["loading"]),

View File

@ -94,6 +94,7 @@ export default {
locale: "",
};
},
inject: ["$showError", "$showSuccess"],
computed: {
...mapState(useAuthStore, ["user"]),
...mapWritableState(useLayoutStore, ["loading"]),

View File

@ -65,7 +65,7 @@ import { mapState, mapWritableState } from "pinia";
import { useAuthStore } from "@/stores/auth";
import { useLayoutStore } from "@/stores/layout";
import { share as api, users } from "@/api";
import moment from "moment";
import dayjs from "dayjs";
import Clipboard from "clipboard";
import Errors from "@/views/Errors.vue";
@ -74,6 +74,7 @@ export default {
components: {
Errors,
},
inject: ["$showError", "$showSuccess"],
computed: {
...mapState(useAuthStore, ["user"]),
...mapWritableState(useLayoutStore, ["loading"]),
@ -135,7 +136,7 @@ export default {
});
},
humanTime(time) {
return moment(time * 1000).fromNow();
return dayjs(time * 1000).fromNow();
},
buildLink(share) {
return api.getShareURL(share);

View File

@ -67,7 +67,6 @@ import { useLayoutStore } from "@/stores/layout";
import { users as api, settings } from "@/api";
import UserForm from "@/components/settings/UserForm.vue";
import Errors from "@/views/Errors.vue";
import deepClone from "lodash.clonedeep";
export default {
name: "user",
@ -86,6 +85,7 @@ export default {
created() {
this.fetchData();
},
inject: ["$showError", "$showSuccess"],
computed: {
...mapState(useAuthStore, ["user"]),
...mapState(useLayoutStore, ["show"]),
@ -161,7 +161,7 @@ export default {
await api.update(user);
if (user.id === this.user.id) {
this.setUser({ ...deepClone(user) });
this.setUser({ ...structuredClone(user) });
}
this.$showSuccess(this.$t("settings.userUpdated"));

View File

@ -1,52 +1,75 @@
import { fileURLToPath, URL } from "node:url";
import path from "node:path";
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import VueI18nPlugin from "@intlify/unplugin-vue-i18n/vite";
import { compression } from "vite-plugin-compression2";
import pluginRewriteAll from "vite-plugin-rewrite-all";
const plugins = [
vue({
template: {
compilerOptions: {
compatConfig: {
MODE: 2,
},
},
},
}),
VueI18nPlugin(),
compression({ include: /\.js$/i, deleteOriginalAssets: true }),
pluginRewriteAll(), // fixes 404 error with paths containing dot in dev server
];
const resolve = {
alias: {
vue: "@vue/compat",
"@/": `${path.resolve(__dirname, "src")}/`,
},
};
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
vue({
template: {
compilerOptions: {
compatConfig: {
MODE: 2,
export default defineConfig(({ command }) => {
if (command === "serve") {
return {
plugins,
resolve,
server: {
proxy: {
"/api/command": {
target: "ws://127.0.0.1:8080",
ws: true,
},
"/api": "http://127.0.0.1:8080",
},
},
};
} else {
// command === 'build'
return {
plugins,
resolve,
base: "",
build: {
rollupOptions: {
input: {
index: fileURLToPath(
new URL(`./public/index.html`, import.meta.url)
),
},
},
},
}),
VueI18nPlugin(),
compression({ include: /\.js$/i, deleteOriginalAssets: true }),
pluginRewriteAll(), // Fixes 404 error with paths containing dot (will be fixed in Vite 5)
],
resolve: {
alias: {
vue: "@vue/compat",
"@/": fileURLToPath(new URL("./src/", import.meta.url)),
},
},
server: {
proxy: {
"/api/command": {
target: "ws://127.0.0.1:8080",
ws: true,
experimental: {
renderBuiltUrl(filename, { hostType }) {
if (hostType === "js") {
return { runtime: `window.__prependStaticUrl("${filename}")` };
} else if (hostType === "html") {
return `[{[ .StaticURL ]}]/${filename}`;
} else {
return { relative: true };
}
},
},
"/api": "http://127.0.0.1:8080",
},
},
base: "",
experimental: {
renderBuiltUrl(filename, { hostType }) {
if (hostType === "js") {
return { runtime: `window.__prependStaticUrl("${filename}")` };
} else if (hostType === "html") {
return `[{[ .StaticURL ]}]/${filename}`;
} else {
return { relative: true };
}
},
},
};
}
});