evcc-io/assets/js/components/Config/YamlModal.vue
2025-01-31 12:26:23 +01:00

141 lines
3.2 KiB
Vue

<template>
<GenericModal ref="modal" :size="size" :title="title" @open="open">
<p v-if="description || docsLink">
<span v-if="description">{{ description + " " }}</span>
<a v-if="docsLink" :href="docsLink" target="_blank">
{{ $t("config.general.docsLink") }}
</a>
</p>
<p v-if="error" class="text-danger" data-testid="error">{{ error }}</p>
<form ref="form" class="container mx-0 px-0">
<div class="editor-container" :style="{ height }">
<YamlEditor v-model="yaml" class="editor" :errorLine="errorLine" />
</div>
<div class="mt-4 d-flex justify-content-between">
<button
type="button"
class="btn btn-link text-muted btn-cancel"
data-bs-dismiss="modal"
>
{{ $t("config.general.cancel") }}
</button>
<button
type="submit"
class="btn btn-primary"
:disabled="saving || nothingChanged"
@click.prevent="save"
>
<span
v-if="saving"
class="spinner-border spinner-border-sm"
role="status"
aria-hidden="true"
></span>
{{ $t("config.general.save") }}
</button>
</div>
</form>
</GenericModal>
</template>
<script>
import GenericModal from "../GenericModal.vue";
import api from "../../api";
import { docsPrefix } from "../../i18n";
import YamlEditor from "./YamlEditor.vue";
export default {
name: "YamlModal",
components: { GenericModal, YamlEditor },
props: {
title: String,
description: String,
docs: String,
endpoint: String,
defaultYaml: String,
size: { type: String, default: "xl" },
},
emits: ["changed"],
data() {
return {
saving: false,
error: "",
errorLine: undefined,
yaml: "",
serverYaml: "",
};
},
computed: {
docsLink() {
return `${docsPrefix()}${this.docs}`;
},
height() {
return Math.max(150, this.yaml.split("\n").length * 18) + 22 + "px";
},
nothingChanged() {
return this.yaml === this.serverYaml && this.yaml !== "";
},
},
methods: {
reset() {
this.yaml = "";
this.serverYaml = "";
this.error = "";
this.saving = false;
this.errorLine = undefined;
},
async open() {
this.reset();
await this.load();
},
async load() {
try {
const { data } = await api.get(this.endpoint);
this.serverYaml = data.result;
this.yaml = data.result || this.defaultYaml;
} catch (e) {
console.error(e);
}
},
async save() {
this.saving = true;
this.error = "";
this.errorLine = undefined;
try {
const data = this.yaml === this.defaultYaml ? "" : this.yaml;
const res = await api.post(this.endpoint, data, {
validateStatus: (code) => [200, 400].includes(code),
});
if (res.status === 200) {
this.$emit("changed");
this.$refs.modal.close();
}
if (res.status === 400) {
this.error = res.data.error;
this.errorLine = res.data.line;
}
} catch (e) {
console.error(e);
}
this.saving = false;
},
},
};
</script>
<style scoped>
.container {
margin-left: calc(var(--bs-gutter-x) * -0.5);
margin-right: calc(var(--bs-gutter-x) * -0.5);
padding-right: 0;
}
.editor-container {
margin: 0 -1rem 0 -1.25rem;
}
/* reset margins on lg */
@media (min-width: 992px) {
.editor-container {
margin: 0;
}
}
</style>