✨Implement file content access functionality.
This commit is contained in:
parent
6142653b3e
commit
210a3d38a0
|
@ -0,0 +1,59 @@
|
|||
import { AgentSocketHandler } from "../agent-socket-handler";
|
||||
import {callbackResult, checkLogin, DockgeSocket, ValidationError} from "../util-server";
|
||||
import { DockgeServer } from "../dockge-server";
|
||||
import { AgentSocket } from "../../common/agent-socket";
|
||||
import { log } from "../log";
|
||||
import { Stack } from "../stack";
|
||||
|
||||
export class FileSocketHandler extends AgentSocketHandler {
|
||||
create(socket: DockgeSocket, server: DockgeServer, agentSocket: AgentSocket) {
|
||||
agentSocket.on("listDir", async (stackName: unknown, path: unknown, callback) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
|
||||
if (typeof(path) !== "string") {
|
||||
throw new ValidationError("Path must be a string");
|
||||
}
|
||||
const stack = await this.getStack(server, stackName);
|
||||
const res = await stack.listFiles(path);
|
||||
callbackResult({
|
||||
ok: true,
|
||||
files: res
|
||||
}, callback);
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
log.warn("agent", e.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
agentSocket.on("getFile", async (stackName: unknown, file: unknown, callback) => {
|
||||
try {
|
||||
checkLogin(socket);
|
||||
|
||||
if (typeof(file) !== "string") {
|
||||
throw new ValidationError("File Path must be a string");
|
||||
}
|
||||
|
||||
const stack = await this.getStack(server, stackName);
|
||||
const content = await stack.getFile(file);
|
||||
|
||||
callbackResult({
|
||||
ok: true,
|
||||
content: content,
|
||||
}, callback);
|
||||
} catch (e) {
|
||||
if (e instanceof Error) {
|
||||
log.warn("agent", e.message);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async getStack(server : DockgeServer, stackName: unknown) {
|
||||
if (typeof(stackName) !== "string") {
|
||||
throw new ValidationError("Stack name must be a string");
|
||||
}
|
||||
return await Stack.getStack(server, stackName);
|
||||
}
|
||||
}
|
|
@ -37,6 +37,7 @@ import { AgentSocketHandler } from "./agent-socket-handler";
|
|||
import { AgentSocket } from "../common/agent-socket";
|
||||
import { ManageAgentSocketHandler } from "./socket-handlers/manage-agent-socket-handler";
|
||||
import { Terminal } from "./terminal";
|
||||
import {FileSocketHandler} from "./agent-socket-handlers/file-socket-handler";
|
||||
|
||||
export class DockgeServer {
|
||||
app : Express;
|
||||
|
@ -69,6 +70,7 @@ export class DockgeServer {
|
|||
agentSocketHandlerList : AgentSocketHandler[] = [
|
||||
new DockerSocketHandler(),
|
||||
new TerminalSocketHandler(),
|
||||
new FileSocketHandler(),
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -547,4 +547,27 @@ export class Stack {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
async listFiles(p: string) {
|
||||
const dataDir = path.join(this.dataDir, p);
|
||||
const files = await fsAsync.readdir(dataDir);
|
||||
const filePromises = files.map(async file => {
|
||||
const filePath = path.join(dataDir, file);
|
||||
const stats = await fsAsync.stat(filePath);
|
||||
return {
|
||||
name: file,
|
||||
path: path.join(p, file),
|
||||
folder: stats.isDirectory(),
|
||||
};
|
||||
});
|
||||
return Promise.all(filePromises);
|
||||
}
|
||||
|
||||
async getFile(p: string) {
|
||||
const file = path.join(this.dataDir, p);
|
||||
console.log(file);
|
||||
const content = await fsAsync.readFile(file, "utf-8");
|
||||
log.debug("file", content);
|
||||
return content;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<script setup lang="ts">
|
||||
<script lang="ts">
|
||||
import { highlight, languages } from "prismjs/components/prism-core";
|
||||
import { PrismEditor } from "vue-prism-editor";
|
||||
import "prismjs/themes/prism-dark.css";
|
||||
|
@ -7,13 +7,9 @@ import "vue-prism-editor/dist/prismeditor.min.css";
|
|||
import "prismjs/components/prism-json.js";
|
||||
import "prismjs/components/prism-yaml";
|
||||
|
||||
import { ref } from "vue";
|
||||
import { defineComponent, ref } from "vue";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import {FileDef} from "../util-frontend";
|
||||
|
||||
const code = ref<string>("");
|
||||
|
||||
const opened = ref<boolean>(false);
|
||||
import { FileDef } from "../util-frontend";
|
||||
|
||||
const allLanguage = [
|
||||
{
|
||||
|
@ -28,41 +24,68 @@ const allLanguage = [
|
|||
}
|
||||
];
|
||||
|
||||
const language = ref({
|
||||
label: "YAML",
|
||||
value: "yaml",
|
||||
lang: languages.yaml
|
||||
});
|
||||
export default defineComponent({
|
||||
name: "FileEditor",
|
||||
components: {
|
||||
PrismEditor,
|
||||
},
|
||||
props: {
|
||||
endpoint: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
stackName: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
allLanguage: allLanguage,
|
||||
code: "",
|
||||
opened: false,
|
||||
disabled: false,
|
||||
language: {
|
||||
label: "YAML",
|
||||
value: "yaml",
|
||||
lang: languages.yaml
|
||||
},
|
||||
fileInfo: {
|
||||
name: "UNTITLED",
|
||||
path: "",
|
||||
folder: false,
|
||||
}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
languageChange(e) {
|
||||
const res = allLanguage.filter(lang => lang.value === e.target.value);
|
||||
if (res.length <= 0) {
|
||||
this.language = allLanguage[0];
|
||||
} else {
|
||||
this.language = res[0];
|
||||
}
|
||||
},
|
||||
|
||||
const fileInfo = ref<FileDef>({
|
||||
name: "UNTITLED",
|
||||
path: "",
|
||||
folder: false,
|
||||
});
|
||||
open(file: FileDef) {
|
||||
this.opened = true;
|
||||
this.disabled = true;
|
||||
this.fileInfo = file;
|
||||
this.$root.emitAgent(this.endpoint, "getFile", this.stackName, file.path, (res) => {
|
||||
this.code = res.content;
|
||||
this.disabled = false;
|
||||
});
|
||||
},
|
||||
|
||||
const languageChange = (e) => {
|
||||
const res = allLanguage.filter(lang => lang.value === e.target.value);
|
||||
if (res.length <= 0) {
|
||||
language.value = allLanguage[0];
|
||||
} else {
|
||||
language.value = res[0];
|
||||
close() {
|
||||
this.opened = false;
|
||||
},
|
||||
|
||||
highlighter(code) {
|
||||
return highlight(code, this.language.lang, this.language.value);
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
const open = (file: FileDef) => {
|
||||
opened.value = true;
|
||||
fileInfo.value = file;
|
||||
};
|
||||
|
||||
const close = () => {
|
||||
opened.value = false;
|
||||
};
|
||||
|
||||
defineExpose({ open });
|
||||
|
||||
const highlighter = (code) => {
|
||||
return highlight(code, language.value.lang, language.value.value);
|
||||
};
|
||||
});
|
||||
</script>
|
||||
|
||||
<template>
|
||||
|
@ -79,7 +102,7 @@ const highlighter = (code) => {
|
|||
</select>
|
||||
</div>
|
||||
<div class="editor-wrapper">
|
||||
<PrismEditor v-model="code" class="my-editor" :highlight="highlighter" line-numbers />
|
||||
<PrismEditor v-model="code" class="my-editor" :readonly="disabled" :highlight="highlighter" line-numbers />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<script lang="ts">
|
||||
import { defineComponent } from "vue";
|
||||
import {FontAwesomeIcon} from "@fortawesome/vue-fontawesome";
|
||||
import { FontAwesomeIcon } from "@fortawesome/vue-fontawesome";
|
||||
import { log } from "../../../backend/log";
|
||||
|
||||
export default defineComponent({
|
||||
name: "Files",
|
||||
components: {FontAwesomeIcon},
|
||||
components: { FontAwesomeIcon },
|
||||
data() {
|
||||
return {
|
||||
files: [
|
||||
|
@ -27,6 +28,16 @@ export default defineComponent({
|
|||
stackName() {
|
||||
return this.$route.params.stackName;
|
||||
},
|
||||
|
||||
endpoint() {
|
||||
return this.$route.params.endpoint || "";
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.$root.emitAgent(this.endpoint, "listDir", "homepage", "/", (res) => {
|
||||
console.log(res.files);
|
||||
this.files = res.files;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
open(file) {
|
||||
|
@ -38,7 +49,7 @@ export default defineComponent({
|
|||
this.$refs.fileEditor.open(file);
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -86,7 +97,7 @@ export default defineComponent({
|
|||
/>
|
||||
</div>
|
||||
|
||||
<FileEditor ref="fileEditor" />
|
||||
<FileEditor :endpoint="endpoint" :stack-name="stackName" ref="fileEditor" />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
|
Loading…
Reference in New Issue