mirror of
https://github.com/Sebclem/hassio-nextcloud-backup.git
synced 2024-11-26 02:52:59 +01:00
🔨 Add form for webdav settings
This commit is contained in:
parent
f3aebdd4ff
commit
96a6e22072
@ -10,7 +10,9 @@ const backupConfigPath = "/data/backupConfigV2.json";
|
|||||||
|
|
||||||
export function validateBackupConfig(config: BackupConfig){
|
export function validateBackupConfig(config: BackupConfig){
|
||||||
const validator = Joi.object(backupConfigValidation);
|
const validator = Joi.object(backupConfigValidation);
|
||||||
return validator.validateAsync(config);
|
return validator.validateAsync(config, {
|
||||||
|
abortEarly: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function saveBackupConfig(config: BackupConfig){
|
export function saveBackupConfig(config: BackupConfig){
|
||||||
|
@ -14,7 +14,9 @@ const NEXTCLOUD_ENDPOINT = "/remote.php/dav/files/$username";
|
|||||||
|
|
||||||
export function validateWebdavConfig(config: WebdavConfig) {
|
export function validateWebdavConfig(config: WebdavConfig) {
|
||||||
const validator = Joi.object(WebdavConfigValidation);
|
const validator = Joi.object(WebdavConfigValidation);
|
||||||
return validator.validateAsync(config);
|
return validator.validateAsync(config, {
|
||||||
|
abortEarly: false
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function saveWebdavConfig(config: WebdavConfig) {
|
export function saveWebdavConfig(config: WebdavConfig) {
|
||||||
|
@ -3,7 +3,7 @@ import { WebdavEndpointType } from "./webdavConfig.js";
|
|||||||
|
|
||||||
|
|
||||||
const WebdavConfigValidation = {
|
const WebdavConfigValidation = {
|
||||||
url: Joi.string().not().empty().required(),
|
url: Joi.string().not().empty().uri().required(),
|
||||||
username: Joi.string().not().empty().required(),
|
username: Joi.string().not().empty().required(),
|
||||||
password: Joi.string().not().empty().required(),
|
password: Joi.string().not().empty().required(),
|
||||||
backupDir: Joi.string().required(),
|
backupDir: Joi.string().required(),
|
||||||
|
1
nextcloud_backup/frontend/.env.development
Normal file
1
nextcloud_backup/frontend/.env.development
Normal file
@ -0,0 +1 @@
|
|||||||
|
VITE_API_URL="http://localhost:3000/"
|
7
nextcloud_backup/frontend/env.d.ts
vendored
7
nextcloud_backup/frontend/env.d.ts
vendored
@ -1 +1,8 @@
|
|||||||
/// <reference types="vite/client" />
|
/// <reference types="vite/client" />
|
||||||
|
|
||||||
|
interface ImportMetaEnv {
|
||||||
|
readonly VITE_API_URL: string;
|
||||||
|
}
|
||||||
|
interface ImportMeta {
|
||||||
|
readonly env: ImportMetaEnv;
|
||||||
|
}
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"pinia": "^2.0.23",
|
"pinia": "^2.0.23",
|
||||||
"roboto-fontface": "*",
|
"roboto-fontface": "*",
|
||||||
"vue": "^3.2.40",
|
"vue": "^3.2.40",
|
||||||
"vuetify": "3.0.0-beta.13",
|
"vuetify": "3.0.0-beta.14",
|
||||||
"webfontloader": "^1.0.0"
|
"webfontloader": "^1.0.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
@ -24,7 +24,7 @@ specifiers:
|
|||||||
vite-plugin-vuetify: ^1.0.0-alpha.12
|
vite-plugin-vuetify: ^1.0.0-alpha.12
|
||||||
vue: ^3.2.40
|
vue: ^3.2.40
|
||||||
vue-tsc: 1.0.7
|
vue-tsc: 1.0.7
|
||||||
vuetify: 3.0.0-beta.13
|
vuetify: 3.0.0-beta.14
|
||||||
webfontloader: ^1.0.0
|
webfontloader: ^1.0.0
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -36,7 +36,7 @@ dependencies:
|
|||||||
pinia: 2.0.23_rg374xhldfcyvjtaj3qktyfz5y
|
pinia: 2.0.23_rg374xhldfcyvjtaj3qktyfz5y
|
||||||
roboto-fontface: 0.10.0
|
roboto-fontface: 0.10.0
|
||||||
vue: 3.2.40
|
vue: 3.2.40
|
||||||
vuetify: 3.0.0-beta.13_vdkwhj2kz5kpysy3rwb432nm3y
|
vuetify: 3.0.0-beta.14_vdkwhj2kz5kpysy3rwb432nm3y
|
||||||
webfontloader: 1.6.28
|
webfontloader: 1.6.28
|
||||||
|
|
||||||
devDependencies:
|
devDependencies:
|
||||||
@ -53,7 +53,7 @@ devDependencies:
|
|||||||
prettier: 2.7.1
|
prettier: 2.7.1
|
||||||
typescript: 4.7.4
|
typescript: 4.7.4
|
||||||
vite: 3.1.7
|
vite: 3.1.7
|
||||||
vite-plugin-vuetify: 1.0.0-alpha.17_l4pgesydsz3cvwqxhtnrp3zlwq
|
vite-plugin-vuetify: 1.0.0-alpha.17_jvcjrjiyr77axku57qj2zhmwla
|
||||||
vue-tsc: 1.0.7_typescript@4.7.4
|
vue-tsc: 1.0.7_typescript@4.7.4
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
@ -482,7 +482,7 @@ packages:
|
|||||||
'@types/node': 16.11.65
|
'@types/node': 16.11.65
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@vuetify/loader-shared/1.6.0_t3dvazyjkhimlko2vtyi5desum:
|
/@vuetify/loader-shared/1.6.0_ufv4csfzemzfiqpf5bhlrg5qhm:
|
||||||
resolution: {integrity: sha512-mRvswe5SIecagmKkL1c0UQx5V9ACKLyEGegOOe5vC3ccFH8rMbyI4AVZaAKm/EnGXKirWJ1umL8RQFcGd+C0tw==}
|
resolution: {integrity: sha512-mRvswe5SIecagmKkL1c0UQx5V9ACKLyEGegOOe5vC3ccFH8rMbyI4AVZaAKm/EnGXKirWJ1umL8RQFcGd+C0tw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vue: ^3.0.0
|
vue: ^3.0.0
|
||||||
@ -491,7 +491,7 @@ packages:
|
|||||||
find-cache-dir: 3.3.2
|
find-cache-dir: 3.3.2
|
||||||
upath: 2.0.1
|
upath: 2.0.1
|
||||||
vue: 3.2.40
|
vue: 3.2.40
|
||||||
vuetify: 3.0.0-beta.13_vdkwhj2kz5kpysy3rwb432nm3y
|
vuetify: 3.0.0-beta.14_vdkwhj2kz5kpysy3rwb432nm3y
|
||||||
|
|
||||||
/acorn-jsx/5.3.2_acorn@8.8.0:
|
/acorn-jsx/5.3.2_acorn@8.8.0:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
@ -2150,18 +2150,18 @@ packages:
|
|||||||
spdx-expression-parse: 3.0.1
|
spdx-expression-parse: 3.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/vite-plugin-vuetify/1.0.0-alpha.17_l4pgesydsz3cvwqxhtnrp3zlwq:
|
/vite-plugin-vuetify/1.0.0-alpha.17_jvcjrjiyr77axku57qj2zhmwla:
|
||||||
resolution: {integrity: sha512-lP4vG+Z3LnIEjI8nSE8/MJwDRQK5OnS2i4zHDu36yyD4E7wmPKyIkWJdkfBIsx/O+PU7dGc/3MeLARgr+RErEQ==}
|
resolution: {integrity: sha512-lP4vG+Z3LnIEjI8nSE8/MJwDRQK5OnS2i4zHDu36yyD4E7wmPKyIkWJdkfBIsx/O+PU7dGc/3MeLARgr+RErEQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^2.7.0 || ^3.0.0
|
vite: ^2.7.0 || ^3.0.0
|
||||||
vuetify: ^3.0.0-beta.4
|
vuetify: ^3.0.0-beta.4
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vuetify/loader-shared': 1.6.0_t3dvazyjkhimlko2vtyi5desum
|
'@vuetify/loader-shared': 1.6.0_ufv4csfzemzfiqpf5bhlrg5qhm
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
upath: 2.0.1
|
upath: 2.0.1
|
||||||
vite: 3.1.7
|
vite: 3.1.7
|
||||||
vuetify: 3.0.0-beta.13_vdkwhj2kz5kpysy3rwb432nm3y
|
vuetify: 3.0.0-beta.14_vdkwhj2kz5kpysy3rwb432nm3y
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- vue
|
- vue
|
||||||
@ -2252,18 +2252,15 @@ packages:
|
|||||||
'@vue/server-renderer': 3.2.40_vue@3.2.40
|
'@vue/server-renderer': 3.2.40_vue@3.2.40
|
||||||
'@vue/shared': 3.2.40
|
'@vue/shared': 3.2.40
|
||||||
|
|
||||||
/vuetify/3.0.0-beta.13_vdkwhj2kz5kpysy3rwb432nm3y:
|
/vuetify/3.0.0-beta.14_vdkwhj2kz5kpysy3rwb432nm3y:
|
||||||
resolution: {integrity: sha512-CgDyKCIBZ0ogKUxRw3gNswx9GA6eSSp7otZcJapWJCVuon/RooQPQjf3bDuRb5ZpJ55NkX13ugjl2nq+b0U8SA==}
|
resolution: {integrity: sha512-7UX2rAcMPGdJ0SGAK+wUvlJTHR0KasYILhg7dV9hLyv9SfaTX4tbOQnSQVf4mXzdFB+5jDyaTs+bOYMVeoqXYg==}
|
||||||
engines: {node: ^12.20 || >=14.13}
|
engines: {node: ^12.20 || >=14.13}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@formatjs/intl': ^1.0.0 || ^2.0.0
|
|
||||||
vite-plugin-vuetify: ^1.0.0-alpha.12
|
vite-plugin-vuetify: ^1.0.0-alpha.12
|
||||||
vue: ^3.2.0
|
vue: ^3.2.0
|
||||||
vue-i18n: ^9.0.0
|
vue-i18n: ^9.0.0
|
||||||
webpack-plugin-vuetify: ^2.0.0-alpha.11
|
webpack-plugin-vuetify: ^2.0.0-alpha.11
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
'@formatjs/intl':
|
|
||||||
optional: true
|
|
||||||
vite-plugin-vuetify:
|
vite-plugin-vuetify:
|
||||||
optional: true
|
optional: true
|
||||||
vue-i18n:
|
vue-i18n:
|
||||||
@ -2271,7 +2268,7 @@ packages:
|
|||||||
webpack-plugin-vuetify:
|
webpack-plugin-vuetify:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
vite-plugin-vuetify: 1.0.0-alpha.17_l4pgesydsz3cvwqxhtnrp3zlwq
|
vite-plugin-vuetify: 1.0.0-alpha.17_jvcjrjiyr77axku57qj2zhmwla
|
||||||
vue: 3.2.40
|
vue: 3.2.40
|
||||||
|
|
||||||
/webfontloader/1.6.28:
|
/webfontloader/1.6.28:
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
<v-main>
|
<v-main>
|
||||||
<navbar-component></navbar-component>
|
<navbar-component></navbar-component>
|
||||||
<message-bar></message-bar>
|
<message-bar></message-bar>
|
||||||
|
<webdav-settings-menu></webdav-settings-menu>
|
||||||
</v-main>
|
</v-main>
|
||||||
</v-app>
|
</v-app>
|
||||||
</template>
|
</template>
|
||||||
@ -10,6 +11,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import NavbarComponent from "./components/NavbarComponent.vue";
|
import NavbarComponent from "./components/NavbarComponent.vue";
|
||||||
import MessageBar from "./components/MessageBar.vue";
|
import MessageBar from "./components/MessageBar.vue";
|
||||||
|
import WebdavSettingsMenu from "./components/settings/WebdavConfigMenu.vue";
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped></style>
|
<style scoped></style>
|
||||||
|
@ -12,19 +12,33 @@
|
|||||||
<v-btn icon id="message-btn">
|
<v-btn icon id="message-btn">
|
||||||
<v-icon>mdi-bell</v-icon>
|
<v-icon>mdi-bell</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
<v-btn icon @click="emit('settingClick')">
|
<v-menu width="210px">
|
||||||
|
<template v-slot:activator="{ props }">
|
||||||
|
<v-btn icon v-bind="props">
|
||||||
<v-icon>mdi-cog</v-icon>
|
<v-icon>mdi-cog</v-icon>
|
||||||
</v-btn>
|
</v-btn>
|
||||||
|
</template>
|
||||||
|
<v-list>
|
||||||
|
<v-list-item
|
||||||
|
title="Cloud settings"
|
||||||
|
@click="dialogStatusStore.webdav = true"
|
||||||
|
prepend-icon="mdi-cloud"
|
||||||
|
></v-list-item>
|
||||||
|
<v-list-item
|
||||||
|
title="Backup settings"
|
||||||
|
prepend-icon="mdi-rotate-left"
|
||||||
|
@click="dialogStatusStore.backup = true"
|
||||||
|
></v-list-item>
|
||||||
|
</v-list>
|
||||||
|
</v-menu>
|
||||||
</v-app-bar>
|
</v-app-bar>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { useDialogStatusStore } from "@/stores/dialogStatus";
|
||||||
import logoUrl from "../assets/logo.svg";
|
import logoUrl from "../assets/logo.svg";
|
||||||
|
|
||||||
const emit = defineEmits<{
|
const dialogStatusStore = useDialogStatusStore();
|
||||||
(e: "settingClick"): void;
|
|
||||||
(e: "notificationClick"): void;
|
|
||||||
}>();
|
|
||||||
</script>
|
</script>
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.shake {
|
.shake {
|
||||||
|
@ -0,0 +1,208 @@
|
|||||||
|
<template>
|
||||||
|
<v-form class="mx-4">
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<div class="text-subtitle-1 text-medium-emphasis">URL</div>
|
||||||
|
<v-text-field
|
||||||
|
placeholder="https://exemple.com"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
prepend-inner-icon="mdi-web"
|
||||||
|
hide-details="auto"
|
||||||
|
v-model="data.url"
|
||||||
|
:error-messages="errors.url"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<div class="text-subtitle-1 text-medium-emphasis">Endpoint</div>
|
||||||
|
<v-select
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
:items="items"
|
||||||
|
hide-details="auto"
|
||||||
|
v-model="data.webdavEndpoint.type"
|
||||||
|
:error-messages="errors.type"
|
||||||
|
>
|
||||||
|
</v-select>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row v-if="data.webdavEndpoint.type == WebdavEndpointType.CUSTOM">
|
||||||
|
<v-col>
|
||||||
|
<div class="text-subtitle-1 text-medium-emphasis">Custom Endpoint</div>
|
||||||
|
<v-text-field
|
||||||
|
placeholder="/remote.php/dav/files/$username"
|
||||||
|
hint="You can use the $username variable"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
hide-details="auto"
|
||||||
|
v-model="data.webdavEndpoint.customEndpoint"
|
||||||
|
:error-messages="errors.customEndpoint"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col class="d-flex align-content-end">
|
||||||
|
<v-switch
|
||||||
|
color="warning"
|
||||||
|
label="Allow Self Signed Certificate"
|
||||||
|
v-model="data.allowSelfSignedCerts"
|
||||||
|
hide-details="auto"
|
||||||
|
density="compact"
|
||||||
|
inset
|
||||||
|
:error-messages="errors.allowSelfSignedCerts"
|
||||||
|
></v-switch>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col><v-divider></v-divider></v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<v-alert type="info" variant="outlined">
|
||||||
|
You need to use <b>App password</b>.<br />
|
||||||
|
More info
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
href="https://github.com/Sebclem/hassio-nextcloud-backup/blob/master/nextcloud_backup/DOCS.md#nextcloud-config"
|
||||||
|
>
|
||||||
|
here.
|
||||||
|
</a>
|
||||||
|
</v-alert>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<div class="text-subtitle-1 text-medium-emphasis">Username</div>
|
||||||
|
<v-text-field
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
placeholder="Username"
|
||||||
|
prepend-inner-icon="mdi-account"
|
||||||
|
hide-details="auto"
|
||||||
|
v-model="data.username"
|
||||||
|
:error-messages="errors.username"
|
||||||
|
>
|
||||||
|
</v-text-field>
|
||||||
|
</v-col>
|
||||||
|
<v-col cols="12" md="6">
|
||||||
|
<div class="text-subtitle-1 text-medium-emphasis">App password</div>
|
||||||
|
<v-text-field
|
||||||
|
placeholder="App password"
|
||||||
|
type="password"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
prepend-inner-icon="mdi-key"
|
||||||
|
hide-details="auto"
|
||||||
|
v-model="data.password"
|
||||||
|
:error-messages="errors.password"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col><v-divider></v-divider></v-col>
|
||||||
|
</v-row>
|
||||||
|
<v-row>
|
||||||
|
<v-col>
|
||||||
|
<div class="text-subtitle-1 text-medium-emphasis">Backup folder</div>
|
||||||
|
<v-text-field
|
||||||
|
placeholder="Backup folder"
|
||||||
|
variant="outlined"
|
||||||
|
density="compact"
|
||||||
|
prepend-inner-icon="mdi-folder"
|
||||||
|
hide-details="auto"
|
||||||
|
v-model="data.backupDir"
|
||||||
|
:error-messages="errors.backupDir"
|
||||||
|
></v-text-field>
|
||||||
|
</v-col>
|
||||||
|
</v-row>
|
||||||
|
</v-form>
|
||||||
|
</template>
|
||||||
|
<script setup lang="ts">
|
||||||
|
import {
|
||||||
|
WebdavEndpointType,
|
||||||
|
type WebdavConfig,
|
||||||
|
} from "../../types/webdavConfig";
|
||||||
|
import {
|
||||||
|
getWebdavConfig,
|
||||||
|
saveWebdavConfig,
|
||||||
|
} from "../../services/ConfigService";
|
||||||
|
import { ref } from "vue";
|
||||||
|
import { HTTPError } from "ky";
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{
|
||||||
|
title: "Nextcloud",
|
||||||
|
value: WebdavEndpointType.NEXTCLOUD,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "Custom",
|
||||||
|
value: WebdavEndpointType.CUSTOM,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const errors = ref({
|
||||||
|
url: [],
|
||||||
|
username: [],
|
||||||
|
password: [],
|
||||||
|
backupDir: [],
|
||||||
|
allowSelfSignedCerts: [],
|
||||||
|
type: [],
|
||||||
|
customEndpoint: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = ref<WebdavConfig>({
|
||||||
|
url: "",
|
||||||
|
allowSelfSignedCerts: false,
|
||||||
|
backupDir: "",
|
||||||
|
username: "",
|
||||||
|
password: "",
|
||||||
|
webdavEndpoint: {
|
||||||
|
type: WebdavEndpointType.NEXTCLOUD,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const emit = defineEmits<{
|
||||||
|
(e: "success"): void;
|
||||||
|
(e: "fail"): void;
|
||||||
|
(e: "loaded"): void;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
clearErrors();
|
||||||
|
saveWebdavConfig(data.value)
|
||||||
|
.then(() => {
|
||||||
|
emit("success");
|
||||||
|
})
|
||||||
|
.catch(async (reason) => {
|
||||||
|
if (reason instanceof HTTPError) {
|
||||||
|
const response = await reason.response.json();
|
||||||
|
if (Array.isArray(response)) {
|
||||||
|
for (let elem of response) {
|
||||||
|
errors.value[elem.context.key as keyof typeof errors.value] =
|
||||||
|
elem.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit("fail");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearErrors() {
|
||||||
|
for (let elem in errors.value) {
|
||||||
|
errors.value[elem as keyof typeof errors.value] = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadData() {
|
||||||
|
console.log("ok");
|
||||||
|
getWebdavConfig().then((value) => {
|
||||||
|
data.value = value;
|
||||||
|
emit("loaded");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
loadData();
|
||||||
|
defineExpose({ save });
|
||||||
|
</script>
|
@ -0,0 +1,66 @@
|
|||||||
|
<template>
|
||||||
|
<v-dialog
|
||||||
|
v-model="dialogStatusStore.webdav"
|
||||||
|
persistent
|
||||||
|
:width="width"
|
||||||
|
:fullscreen="xs"
|
||||||
|
scrollable
|
||||||
|
>
|
||||||
|
<v-card>
|
||||||
|
<v-card-title class="text-center">Cloud Settings</v-card-title>
|
||||||
|
<v-divider></v-divider>
|
||||||
|
<v-card-text>
|
||||||
|
<webdav-settings-form
|
||||||
|
ref="form"
|
||||||
|
@fail="saving = false"
|
||||||
|
@success="dialogStatusStore.webdav = false"
|
||||||
|
@loaded="loading = false"
|
||||||
|
></webdav-settings-form>
|
||||||
|
</v-card-text>
|
||||||
|
<v-divider></v-divider>
|
||||||
|
<v-card-actions class="justify-end">
|
||||||
|
<v-btn
|
||||||
|
color="red"
|
||||||
|
@click="dialogStatusStore.webdav = false"
|
||||||
|
:disabled="saving"
|
||||||
|
>Cancel</v-btn
|
||||||
|
>
|
||||||
|
<v-btn color="success" @click="save()" :loading="saveLoading"
|
||||||
|
>Save</v-btn
|
||||||
|
>
|
||||||
|
</v-card-actions>
|
||||||
|
</v-card>
|
||||||
|
</v-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { useDialogStatusStore } from "@/stores/dialogStatus";
|
||||||
|
import { computed, ref } from "vue";
|
||||||
|
import { useDisplay } from "vuetify/lib/framework.mjs";
|
||||||
|
import WebdavSettingsForm from "./WebdavConfigForm.vue";
|
||||||
|
|
||||||
|
const dialogStatusStore = useDialogStatusStore();
|
||||||
|
const form = ref<InstanceType<typeof WebdavSettingsForm> | null>(null);
|
||||||
|
const loading = ref(true);
|
||||||
|
const saving = ref(false);
|
||||||
|
const { xs, mdAndDown } = useDisplay();
|
||||||
|
|
||||||
|
let saveLoading = computed(() => {
|
||||||
|
return saving.value || loading.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
const width = computed(() => {
|
||||||
|
if (xs.value) {
|
||||||
|
return undefined;
|
||||||
|
} else if (mdAndDown.value) {
|
||||||
|
return "80%";
|
||||||
|
} else {
|
||||||
|
return "50%";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function save() {
|
||||||
|
saving.value = true;
|
||||||
|
form.value?.save();
|
||||||
|
}
|
||||||
|
</script>
|
@ -1,8 +1,9 @@
|
|||||||
|
import { createPinia } from "pinia";
|
||||||
import { createApp } from "vue";
|
import { createApp } from "vue";
|
||||||
import App from "./App.vue";
|
import App from "./App.vue";
|
||||||
import vuetify from "./plugins/vuetify";
|
import vuetify from "./plugins/vuetify";
|
||||||
import { loadFonts } from "./plugins/webfontloader";
|
import { loadFonts } from "./plugins/webfontloader";
|
||||||
|
|
||||||
loadFonts();
|
loadFonts();
|
||||||
|
const pinia = createPinia();
|
||||||
createApp(App).use(vuetify).mount("#app");
|
createApp(App).use(vuetify).use(pinia).mount("#app");
|
||||||
|
14
nextcloud_backup/frontend/src/services/ConfigService.ts
Normal file
14
nextcloud_backup/frontend/src/services/ConfigService.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import type { WebdavConfig } from "@/types/webdavConfig";
|
||||||
|
import kyClient from "./kyClient";
|
||||||
|
|
||||||
|
export function getWebdavConfig() {
|
||||||
|
return kyClient.get("config/webdav").json<WebdavConfig>();
|
||||||
|
}
|
||||||
|
|
||||||
|
export function saveWebdavConfig(config: WebdavConfig) {
|
||||||
|
return kyClient
|
||||||
|
.put("config/webdav", {
|
||||||
|
json: config,
|
||||||
|
})
|
||||||
|
.json();
|
||||||
|
}
|
@ -1,7 +1,6 @@
|
|||||||
import ky from "ky";
|
import ky from "ky";
|
||||||
|
|
||||||
const kyClient = ky.create({
|
const kyClient = ky.create({
|
||||||
prefixUrl: "http://localhost:3000/v2/api",
|
prefixUrl: `${import.meta.env.VITE_API_URL}v2/api`,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default kyClient;
|
export default kyClient;
|
||||||
|
8
nextcloud_backup/frontend/src/stores/dialogStatus.ts
Normal file
8
nextcloud_backup/frontend/src/stores/dialogStatus.ts
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
import { ref } from "vue";
|
||||||
|
import { defineStore } from "pinia";
|
||||||
|
|
||||||
|
export const useDialogStatusStore = defineStore("dialogStatus", () => {
|
||||||
|
const webdav = ref(false);
|
||||||
|
const backup = ref(false);
|
||||||
|
return { webdav, backup };
|
||||||
|
});
|
16
nextcloud_backup/frontend/src/types/webdavConfig.ts
Normal file
16
nextcloud_backup/frontend/src/types/webdavConfig.ts
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
export enum WebdavEndpointType {
|
||||||
|
NEXTCLOUD = "NEXTCLOUD",
|
||||||
|
CUSTOM = "CUSTOM",
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WebdavConfig {
|
||||||
|
url: string;
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
backupDir: string;
|
||||||
|
allowSelfSignedCerts: boolean;
|
||||||
|
webdavEndpoint: {
|
||||||
|
type: WebdavEndpointType;
|
||||||
|
customEndpoint?: string;
|
||||||
|
};
|
||||||
|
}
|
@ -2,7 +2,8 @@
|
|||||||
"extends": [
|
"extends": [
|
||||||
"config:base",
|
"config:base",
|
||||||
":prHourlyLimitNone",
|
":prHourlyLimitNone",
|
||||||
":prConcurrentLimitNone"
|
":prConcurrentLimitNone",
|
||||||
|
"group:allNonMajor"
|
||||||
],
|
],
|
||||||
"commitMessagePrefix": ":arrow_up:",
|
"commitMessagePrefix": ":arrow_up:",
|
||||||
"regexManagers": [
|
"regexManagers": [
|
||||||
@ -15,5 +16,8 @@
|
|||||||
"datasourceTemplate": "docker",
|
"datasourceTemplate": "docker",
|
||||||
"versioningTemplate": "semver"
|
"versioningTemplate": "semver"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"vulnerabilityAlerts": {
|
||||||
|
"enabled": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user