Updated editor to composition api & typescript.
This commit is contained in:
parent
7bc4a21a9d
commit
e5aba2fdec
1
frontend/src/types/file.d.ts
vendored
1
frontend/src/types/file.d.ts
vendored
@ -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 {
|
||||||
|
|||||||
@ -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>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user