Compare commits

...

4 Commits

Author SHA1 Message Date
2c03791db5
Fix alert view 2024-07-12 17:07:00 +02:00
049beb53b8
Add message on cloud delete 2024-07-12 17:06:51 +02:00
bd0fbe81c2
Rework env selection 2024-07-12 16:44:04 +02:00
a22962902d
Fix chunked upload content size issue 2024-07-12 16:41:52 +02:00
7 changed files with 89 additions and 63 deletions

View File

@ -1,8 +1,7 @@
import cookieParser from "cookie-parser"; import cookieParser from "cookie-parser";
import cors from "cors"; import cors from "cors";
import errorHandler from "errorhandler";
import express from "express"; import express from "express";
import createError from "http-errors";
import morgan from "morgan"; import morgan from "morgan";
import path from "path"; import path from "path";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
@ -20,10 +19,11 @@ app.use(
); );
app.set("port", process.env.PORT || 3000); app.set("port", process.env.PORT || 3000);
if (process.env.ACCESS_LOG == "true") {
// app.use( app.use(
// morgan("dev", { stream: { write: (message) => logger.debug(message) } }) morgan("dev", { stream: { write: (message) => logger.debug(message) } })
// ); );
}
app.use(express.json()); app.use(express.json());
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));
app.use(cookieParser()); app.use(cookieParser());
@ -36,15 +36,4 @@ app.use("/v2/api/", apiV2Router);
---------------------------------------------------------- ----------------------------------------------------------
*/ */
// error handler
if (app.get("env") == "development") {
// catch 404 and forward to error handler
app.use((req, res, next) => {
next(createError(404));
});
// only use in development
app.use(errorHandler());
}
export default app; export default app;

View File

@ -1,16 +1,21 @@
import errorHandler from "errorhandler";
import "./env.js"; import "./env.js";
import errorHandler from "errorhandler";
import figlet from "figlet";
import createError from "http-errors";
import kleur from "kleur";
import app from "./app.js"; import app from "./app.js";
import logger from "./config/winston.js"; import logger from "./config/winston.js";
import postInit from "./postInit.js"; import postInit from "./postInit.js";
import figlet from "figlet";
import kleur from "kleur";
/** /**
* Error Handler. Provides full stack * Error Handler. Provides full stack
*/ */
if (process.env.NODE_ENV === "development") { if (process.env.NODE_ENV === "development") {
app.use(errorHandler()); app.use(errorHandler());
app.use((req, res, next) => {
next(createError(404));
});
} }
/** /**
@ -22,7 +27,7 @@ const server = app.listen(app.get("port"), () => {
`App is running at ` + `App is running at ` +
kleur.green().bold(`http://localhost:${app.get("port")}`) + kleur.green().bold(`http://localhost:${app.get("port")}`) +
" in " + " in " +
kleur.green().bold(app.get("env") as string) + kleur.green().bold(process.env.NODE_ENV || "production") +
" mode" " mode"
); );
logger.info(kleur.red().bold("Press CTRL-C to stop")); logger.info(kleur.red().bold("Press CTRL-C to stop"));

View File

@ -343,7 +343,7 @@ export async function chunkedUpload(
const finalDestination = config.url + getEndpoint(config) + webdavPath; const finalDestination = config.url + getEndpoint(config) + webdavPath;
const status = statusTools.getStatus(); const status = statusTools.getStatus();
status.status = States.BKUP_UPLOAD_CLOUD; status.status = States.BKUP_UPLOAD_CLOUD;
status.progress = 0; status.progress = -1;
statusTools.setStatus(status); statusTools.setStatus(status);
try { try {
await initChunkedUpload(chunkedUrl, finalDestination, config); await initChunkedUpload(chunkedUrl, finalDestination, config);
@ -365,16 +365,21 @@ export async function chunkedUpload(
logger.error((err as Error).message); logger.error((err as Error).message);
} }
fs.unlinkSync(localPath); fs.unlinkSync(localPath);
const status = statusTools.getStatus();
status.status = States.IDLE;
status.progress = undefined;
statusTools.setStatus(status);
throw err; throw err;
} }
let start = 0; let start = 0;
let end = fileSize > CHUNK_SIZE ? CHUNK_SIZE : fileSize; let end = Math.min(CHUNK_SIZE - 1, fileSize - 1);
let current_size = end;
let current_size = end + 1;
// const uploadedBytes = 0; // const uploadedBytes = 0;
let i = 0; let i = 1;
while (start < fileSize) { while (start < fileSize - 1) {
const chunk = fs.createReadStream(localPath, { start, end }); const chunk = fs.createReadStream(localPath, { start, end });
try { try {
const chunckNumber = i.toString().padStart(CHUNK_NUMBER_SIZE, "0"); const chunckNumber = i.toString().padStart(CHUNK_NUMBER_SIZE, "0");
@ -386,9 +391,9 @@ export async function chunkedUpload(
fileSize, fileSize,
config config
); );
start = end; start = end + 1;
end = Math.min(start + CHUNK_SIZE, fileSize - 1); end = Math.min(start + CHUNK_SIZE - 1, fileSize - 1);
current_size = end - start; current_size = end - start + 1;
i++; i++;
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
@ -408,6 +413,10 @@ export async function chunkedUpload(
logger.error(`Code: ${(error as PlainResponse).statusCode}`); logger.error(`Code: ${(error as PlainResponse).statusCode}`);
logger.error(`Body: ${(error as PlainResponse).body as string}`); logger.error(`Body: ${(error as PlainResponse).body as string}`);
} }
const status = statusTools.getStatus();
status.status = States.IDLE;
status.progress = undefined;
statusTools.setStatus(status);
throw error; throw error;
} }
} }
@ -435,6 +444,10 @@ export async function chunkedUpload(
logger.error((err as Error).message); logger.error((err as Error).message);
} }
fs.unlinkSync(localPath); fs.unlinkSync(localPath);
const status = statusTools.getStatus();
status.status = States.IDLE;
status.progress = undefined;
statusTools.setStatus(status);
throw err; throw err;
} }
} }
@ -452,6 +465,7 @@ export function uploadChunk(
logger.debug(`...URI: ${encodeURI(url)}`); logger.debug(`...URI: ${encodeURI(url)}`);
logger.debug(`...Final destination: ${encodeURI(finalDestination)}`); logger.debug(`...Final destination: ${encodeURI(finalDestination)}`);
logger.debug(`...Chunk size: ${contentLength}`); logger.debug(`...Chunk size: ${contentLength}`);
logger.debug(`...Total size: ${totalLength}`);
got.stream got.stream
.put(url, { .put(url, {
headers: { headers: {

View File

@ -1,35 +1,37 @@
<template> <template>
<v-fade-transition> <v-fade-transition>
<div id="alertContainer" v-if="alertVisible"> <div id="parent" v-if="alertVisible">
<v-slide-x-transition group tag="div"> <div id="alertContainer">
<v-alert <v-slide-x-transition group tag="div">
v-for="alert of alertList" <v-alert
v-bind:key="alert.id" v-for="alert of alertList"
elevation="24" v-bind:key="alert.id"
:type="alert.type" elevation="24"
border="start" :type="alert.type"
class="mb-2" border="start"
> class="mb-2"
<v-row dense> >
<v-col v-html="alert.message"></v-col> <v-row dense>
<v-col cols="2"> <v-col v-html="alert.message"></v-col>
<v-btn <v-col cols="2">
class="d-inline" <v-btn
size="30" class="d-inline"
variant="text" size="30"
rounded variant="text"
icon="$close" rounded
@click="alertStore.remove(alert.id)" icon="$close"
></v-btn> @click="alertStore.remove(alert.id)"
</v-col> ></v-btn>
</v-row> </v-col>
</v-row>
<v-progress-linear <v-progress-linear
:max="alertStore.timeOutValue" :max="alertStore.timeOutValue"
:model-value="alert.timeOut" :model-value="alert.timeOut"
></v-progress-linear> ></v-progress-linear>
</v-alert> </v-alert>
</v-slide-x-transition> </v-slide-x-transition>
</div>
</div> </div>
</v-fade-transition> </v-fade-transition>
</template> </template>
@ -45,11 +47,17 @@ const { alertList } = storeToRefs(alertStore);
const alertVisible = computed(() => alertList.value.length > 0); const alertVisible = computed(() => alertList.value.length > 0);
</script> </script>
<style> <style>
#alertContainer { #parent {
position: absolute; position: absolute;
top: 70px; top: 70px;
right: 20px; right: 20px;
z-index: 99999; z-index: 99999;
height: 100vh;
#alertContainer {
position: sticky;
top: 80px;
right: 20px;
}
} }
</style> </style>
@/store/alert @/store/alert

View File

@ -32,9 +32,9 @@
<script setup lang="ts"> <script setup lang="ts">
import { useMenuSize } from "@/composable/menuSize"; import { useMenuSize } from "@/composable/menuSize";
import { deleteWebdabBackup } from "@/services/webdavService"; import { deleteWebdabBackup } from "@/services/webdavService";
import { useAlertStore } from "@/store/alert";
import type { WebdavBackup } from "@/types/webdav"; import type { WebdavBackup } from "@/types/webdav";
import { computed, ref } from "vue"; import { ref } from "vue";
import { useDisplay } from "vuetify/dist/vuetify";
const dialog = ref(false); const dialog = ref(false);
const loading = ref(false); const loading = ref(false);
@ -42,6 +42,11 @@ const item = ref<WebdavBackup | null>(null);
const { width, isFullScreen } = useMenuSize(); const { width, isFullScreen } = useMenuSize();
const emit = defineEmits<{
(e: "deleted"): void;
}>();
const alertStore = useAlertStore();
function confirm() { function confirm() {
loading.value = true; loading.value = true;
if (item.value) { if (item.value) {
@ -49,9 +54,12 @@ function confirm() {
.then(() => { .then(() => {
loading.value = false; loading.value = false;
dialog.value = false; dialog.value = false;
alertStore.add("success", "Backup deleted from cloud");
emit("deleted");
}) })
.catch(() => { .catch(() => {
loading.value = false; loading.value = false;
alertStore.add("error", "Fail to deleted backup from cloud");
}); });
} }
} }

View File

@ -76,7 +76,10 @@
</v-row> </v-row>
</v-card-text> </v-card-text>
</v-card> </v-card>
<cloud-delete-dialog ref="deleteDialog"></cloud-delete-dialog> <cloud-delete-dialog
ref="deleteDialog"
@deleted="refreshBackup"
></cloud-delete-dialog>
</div> </div>
</template> </template>

View File

@ -69,4 +69,3 @@ function saved() {
alertStore.add("success", "Backup settings saved !"); alertStore.add("success", "Backup settings saved !");
} }
</script> </script>
@/store/dialogStatus@/store/alert