Updated editor to composition api & typescript.

This commit is contained in:
Joep 2023-09-21 22:32:35 +02:00
parent 7bc4a21a9d
commit e5aba2fdec
No known key found for this signature in database
GPG Key ID: 6F5588F1DC2A8209
2 changed files with 69 additions and 104 deletions

View File

@ -20,6 +20,7 @@ interface Resource extends ResourceBase {
token?: string; token?: string;
index?: number; index?: number;
subtitles?: string[]; subtitles?: string[];
content?: string;
} }
// interface ResourceItem extends ResourceBase { // interface ResourceItem extends ResourceBase {

View File

@ -1,149 +1,113 @@
<template> <template>
<div id="editor-container"> <div id="editor-container">
<header-bar> <header-bar>
<action icon="close" :label="$t('buttons.close')" @action="close()" /> <action icon="close" :label="t('buttons.close')" @action="close()" />
<title>{{ req.name }}</title> <title>{{ fileStore.req?.name ?? "" }}</title>
<action <action
v-if="user.perm.modify" v-if="authStore.user?.perm.modify"
id="save-button" id="save-button"
icon="save" icon="save"
:label="$t('buttons.save')" :label="t('buttons.save')"
@action="save()" @action="save()"
/> />
</header-bar> </header-bar>
<breadcrumbs base="/files" noLink /> <Breadcrumbs base="/files" noLink />
<form id="editor"></form> <form id="editor"></form>
</div> </div>
</template> </template>
<script> <script setup lang="ts">
import { mapActions, mapState } from "pinia";
import { files as api } from "@/api"; import { files as api } from "@/api";
import { theme } from "@/utils/constants"; import { theme } from "@/utils/constants";
import buttons from "@/utils/buttons"; import buttons from "@/utils/buttons";
import url from "@/utils/url"; import url from "@/utils/url";
import { Ace, version as ace_version } from "ace-builds";
import { version as ace_version } from "ace-builds"; // @ts-ignore
import ace from "ace-builds/src-min-noconflict/ace.js"; import ace from "ace-builds/src-min-noconflict/ace.js";
// @ts-ignore
import modelist from "ace-builds/src-min-noconflict/ext-modelist.js"; import modelist from "ace-builds/src-min-noconflict/ext-modelist.js";
import HeaderBar from "@/components/header/HeaderBar.vue"; import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action.vue"; import Action from "@/components/header/Action.vue";
import Breadcrumbs from "@/components/Breadcrumbs.vue"; import Breadcrumbs from "@/components/Breadcrumbs.vue";
import { useAuthStore } from "@/stores/auth"; import { useAuthStore } from "@/stores/auth";
import { useFileStore } from "@/stores/file"; import { useFileStore } from "@/stores/file";
import { inject, onBeforeUnmount, onMounted, ref } from "vue";
import { useRoute, useRouter } from "vue-router";
import { useI18n } from "vue-i18n";
export default { const $showError = inject<IToastError>("$showError")!;
name: "editor",
components: {
HeaderBar,
Action,
Breadcrumbs,
},
data: function () {
return {};
},
inject: ["$showError"],
computed: {
...mapState(useAuthStore, ["user"]),
...mapState(useFileStore, ["req"]),
breadcrumbs() {
let parts = this.$route.path.split("/");
if (parts[0] === "") { const fileStore = useFileStore();
parts.shift(); const authStore = useAuthStore();
}
if (parts[parts.length - 1] === "") { const { t } = useI18n();
parts.pop();
}
let breadcrumbs = []; const route = useRoute();
const router = useRouter();
for (let i = 0; i < parts.length; i++) { const editor = ref<Ace.Editor | null>(null);
breadcrumbs.push({ name: decodeURIComponent(parts[i]) });
}
breadcrumbs.shift(); onMounted(() => {
window.addEventListener("keydown", keyEvent);
if (breadcrumbs.length > 3) { const fileContent = fileStore.req?.content || "";
while (breadcrumbs.length !== 4) {
breadcrumbs.shift();
}
breadcrumbs[0].name = "..."; ace.config.set(
} "basePath",
`https://cdn.jsdelivr.net/npm/ace-builds@${ace_version}/src-min-noconflict/`
);
return breadcrumbs; editor.value = ace.edit("editor", {
}, value: fileContent,
}, showPrintMargin: false,
created() { readOnly: fileStore.req?.type === "textImmutable",
window.addEventListener("keydown", this.keyEvent); theme: "ace/theme/chrome",
}, mode: modelist.getModeForPath(fileStore.req?.name).mode,
beforeUnmount() { wrap: true,
window.removeEventListener("keydown", this.keyEvent); });
this.editor.destroy();
},
mounted: function () {
const fileContent = this.req.content || "";
ace.config.set( if (theme == "dark") {
"basePath", editor.value?.setTheme("ace/theme/twilight");
`https://cdn.jsdelivr.net/npm/ace-builds@${ace_version}/src-min-noconflict/` }
); });
this.editor = ace.edit("editor", { onBeforeUnmount(() => {
value: fileContent, window.removeEventListener("keydown", keyEvent);
showPrintMargin: false, editor.value?.destroy();
readOnly: this.req.type === "textImmutable", });
theme: "ace/theme/chrome",
mode: modelist.getModeForPath(this.req.name).mode,
wrap: true,
});
if (theme == "dark") { const keyEvent = (event: KeyboardEvent) => {
this.editor.setTheme("ace/theme/twilight"); if (!event.ctrlKey && !event.metaKey) {
} return;
}, }
methods: {
...mapActions(useFileStore, ["updateRequest"]),
back() {
let uri = url.removeLastDir(this.$route.path) + "/";
this.$router.push({ path: uri });
},
keyEvent(event) {
if (!event.ctrlKey && !event.metaKey) {
return;
}
if (String.fromCharCode(event.which).toLowerCase() !== "s") { if (String.fromCharCode(event.which).toLowerCase() !== "s") {
return; return;
} }
event.preventDefault(); event.preventDefault();
this.save(); save();
}, };
async save() {
const button = "save";
buttons.loading("save");
try { const save = async () => {
await api.put(this.$route.path, this.editor.getValue()); const button = "save";
buttons.success(button); buttons.loading("save");
} catch (e) {
buttons.done(button);
this.$showError(e);
}
},
close() {
this.updateRequest({});
let uri = url.removeLastDir(this.$route.path) + "/"; try {
this.$router.push({ path: uri }); await api.put(route.path, editor.value?.getValue());
}, buttons.success(button);
}, } catch (e: any) {
buttons.done(button);
$showError(e);
}
};
const close = () => {
fileStore.updateRequest(null);
let uri = url.removeLastDir(route.path) + "/";
router.push({ path: uri });
}; };
</script> </script>