Files
filebrowser/frontend/src/views/files/Editor.vue
kloon15 5100e587d7 feat: migrate to vue 3 (#2689)
---------

Co-authored-by: Joep <jcbuhre@gmail.com>
Co-authored-by: Omar Hussein <omarmohammad1951@gmail.com>
Co-authored-by: Oleg Lobanov <oleg@lobanov.me>
2024-04-01 17:18:22 +02:00

130 lines
3.2 KiB
Vue

<template>
<div id="editor-container" @touchmove.prevent.stop @wheel.prevent.stop>
<header-bar>
<action icon="close" :label="t('buttons.close')" @action="close()" />
<title>{{ fileStore.req?.name ?? "" }}</title>
<action
v-if="authStore.user?.perm.modify"
id="save-button"
icon="save"
:label="t('buttons.save')"
@action="save()"
/>
</header-bar>
<Breadcrumbs base="/files" noLink />
<form id="editor"></form>
</div>
</template>
<script setup lang="ts">
import { files as api } from "@/api";
import buttons from "@/utils/buttons";
import url from "@/utils/url";
import ace, { Ace, version as ace_version } from "ace-builds";
import modelist from "ace-builds/src-noconflict/ext-modelist";
import "ace-builds/src-noconflict/ext-language_tools";
import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action.vue";
import Breadcrumbs from "@/components/Breadcrumbs.vue";
import { useAuthStore } from "@/stores/auth";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
import { inject, onBeforeUnmount, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useI18n } from "vue-i18n";
import { getTheme } from "@/utils/theme";
const $showError = inject<IToastError>("$showError")!;
const fileStore = useFileStore();
const authStore = useAuthStore();
const layoutStore = useLayoutStore();
const { t } = useI18n();
const route = useRoute();
const router = useRouter();
const editor = ref<Ace.Editor | null>(null);
onMounted(() => {
window.addEventListener("keydown", keyEvent);
const fileContent = fileStore.req?.content || "";
ace.config.set(
"basePath",
`https://cdn.jsdelivr.net/npm/ace-builds@${ace_version}/src-min-noconflict/`
);
editor.value = ace.edit("editor", {
value: fileContent,
showPrintMargin: false,
readOnly: fileStore.req?.type === "textImmutable",
theme: "ace/theme/chrome",
mode: modelist.getModeForPath(fileStore.req?.name).mode,
wrap: true,
enableBasicAutocompletion: true,
enableLiveAutocompletion: true,
enableSnippets: true,
});
if (getTheme() === "dark") {
editor.value!.setTheme("ace/theme/twilight");
}
editor.value.focus();
});
onBeforeUnmount(() => {
window.removeEventListener("keydown", keyEvent);
editor.value?.destroy();
});
const keyEvent = (event: KeyboardEvent) => {
if (event.code === "Escape") {
close();
}
if (!event.ctrlKey && !event.metaKey) {
return;
}
if (event.key !== "s") {
return;
}
event.preventDefault();
save();
};
const save = async () => {
const button = "save";
buttons.loading("save");
try {
await api.put(route.path, editor.value?.getValue());
editor.value?.session.getUndoManager().markClean();
buttons.success(button);
} catch (e: any) {
buttons.done(button);
$showError(e);
}
};
const close = () => {
if (!editor.value?.session.getUndoManager().isClean()) {
layoutStore.showHover("discardEditorChanges");
return;
}
fileStore.updateRequest(null);
let uri = url.removeLastDir(route.path) + "/";
router.push({ path: uri });
};
</script>