fixed sanitizeFilename for backend\API,

added new API call attachmentDownload,
fixed attachment URL to call attachmentDownload,
refactoring Report.vue for <script setup>
This commit is contained in:
2025-10-16 01:40:44 +02:00
parent ed3d202488
commit 3e9056f4a6
4 changed files with 225 additions and 169 deletions

View File

@ -2,10 +2,10 @@
* Generated by APIlite
* https://gitea.tpsoft.org/TPsoft.org/APIlite
*
* 2025-10-01 00:23:37 */
* 2025-10-16 01:38:51 */
class backend {
endpont = import.meta.env.VITE_BACKENDAPI_URL;
endpoint = import.meta.env.VITE_BACKENDAPI_URL;
/* ----------------------------------------------------
* General API call
@ -28,7 +28,7 @@ class backend {
if (typeof val == 'object') val = JSON.stringify(val);
form_data.append(key, val);
});
xhttp.open('POST', this.endpont + '?action=' + method);
xhttp.open('POST', this.endpoint + '?action=' + method);
xhttp.send(form_data);
}
@ -107,6 +107,10 @@ class backend {
return this.callPromise('attachmentDelete', {attachment_id: attachment_id});
}
attachmentDownload(filename) {
return this.callPromise('attachmentDownload', {filename: filename});
}
};

View File

@ -89,9 +89,9 @@
v-else-if="attachment.attachment_type == 'file'"
class="attachment-file"
>
<a :href="attachment.attachment_content" target="_blank">Stiahnut {{ attachment.attachment_content.split('/').pop().split('?')[0].split('#')[0] }}</a>
<a :href="backend.endpoint + attachment.attachment_content" target="_blank">Stiahnut {{ attachment.attachment_content.split('/').pop().split('?')[0].split('#')[0] }}</a>
<br>
<img :src="attachment.attachment_content" v-if="isImageUrl(attachment.attachment_content)" />
<img :src="backend.endpoint + attachment.attachment_content" v-if="isImageUrl(attachment.attachment_content)" />
</div>
<div v-else class="attachment-content">
Neznamy typ prilohy: <strong>{{ attachment.attachment_type }}</strong>
@ -144,7 +144,9 @@
</div>
</template>
<script>
<script setup>
import { onMounted, ref } from "vue";
import { router } from "../router";
import backend from "../backend";
import FullScreenLoader from "../components/FullScreenLoader.vue";
import JSConfetti from 'js-confetti'
@ -152,164 +154,168 @@ import JSConfetti from 'js-confetti'
let tadas = ['/sounds/tada.mp3', '/sounds/tada2.mp3', '/sounds/crazy-phrog-short.mp3'];
const jungle = new Audio(tadas[Math.floor(Math.random() * tadas.length)]);
export default {
name: "Report",
components: { FullScreenLoader },
data() {
return {
loading: false,
report_id: this.$route.params.id,
report: {
report_id: 0,
report_title: "Nacitavam report",
report_description: "...",
report_status: 4,
report_group: "--",
report_priority: 1,
created_dt: "--",
ordnum: 0,
},
editable: true,
attachments: [
{
attachment_id: 0,
attachment_type: "comment",
attachment_content: "Nacitavam report",
created_dt: "--",
},
],
attachmentNewFiles: null,
selectedFiles: [],
selectedFilesContent: [],
};
const loading = ref(false);
const report_id = router.currentRoute.value.params.id;
const report = ref({
report_id: 0,
report_title: "Nacitavam report",
report_description: "...",
report_status: 4,
report_group: "--",
report_priority: 1,
created_dt: "--",
ordnum: 0,
});
const editable = ref(true);
const attachments = ref([
{
attachment_id: 0,
attachment_type: "comment",
attachment_content: "Nacitavam report",
created_dt: "--",
},
mounted() {
// console.log(this.report_id);
this.loadReportData();
},
methods: {
loadReportData() {
backend.get(this.report_id).then((response) => {
this.report = response.data;
// console.log(this.report);
this.editable = response.data.report_status < 4;
]);
const attachmentNewFiles = ref(null);
let selectedFiles = [];
let selectedFilesContent = [];
onMounted(() => {
// console.log(report_id);
loadReportData();
});
function loadReportData() {
backend.get(report_id).then((response) => {
report.value = response.data;
// console.log(report);
editable.value = response.data.report_status < 4;
});
backend.attachmentGetAll(report_id).then((response) => {
attachments.value = response.data;
// console.log(attachments);
});
}
function onTitleChange(event) {
backend.update(report_id, { report_title: event.target.innerText });
}
function onDescriptionChange(event) {
backend.update(report_id, {
report_description: event.target.innerText,
});
}
function reportDelete() {
if (!confirm("Naozaj chcete report zmazať?")) return;
loading = true;
backend.delete(report_id).then(() => {
router.push("/");
});
}
function reportDone() {
backend.update(report_id, {
report_status: 4,
}).then(() => {
jungle.play();
const confetti = new JSConfetti();
confetti.addConfetti();
setTimeout(() => {
router.push("/");
}, 3000);
});
}
function attachmentAdd() {
let comment = $refs.attachmentNewContent.value;
if (comment.trim().length > 0) {
loading = true;
backend
.attachmentAdd(
report_id,
"comment",
attachmentNewContent.value
)
.then(() => {
$refs.attachmentNewContent.value = "";
loadReportData();
loading = false;
});
backend.attachmentGetAll(this.report_id).then((response) => {
this.attachments = response.data;
// console.log(this.attachments);
});
},
onTitleChange(event) {
backend.update(this.report_id, { report_title: event.target.innerText });
},
onDescriptionChange(event) {
backend.update(this.report_id, {
report_description: event.target.innerText,
});
},
reportDelete() {
if (!confirm("Naozaj chcete report zmazať?")) return;
this.loading = true;
backend.delete(this.report_id).then(() => {
this.$router.push("/");
});
},
reportDone() {
backend.update(this.report_id, {
report_status: 4,
}).then(() => {
jungle.play();
const confetti = new JSConfetti();
confetti.addConfetti();
setTimeout(() => {
this.$router.push("/");
}, 3000);
});
},
attachmentAdd() {
let comment = this.$refs.attachmentNewContent.value;
if (comment.trim().length > 0) {
this.loading = true;
backend
.attachmentAdd(
this.report_id,
"comment",
this.$refs.attachmentNewContent.value
)
.then(() => {
this.$refs.attachmentNewContent.value = "";
this.loadReportData();
this.loading = false;
});
}
if (this.selectedFiles.length > 0) {
let for_upload = this.selectedFiles.length;
this.loading = true;
for (let i = 0; i < this.selectedFiles.length; i++) {
backend
.attachmentAdd(this.report_id, "file", {
'filename': this.selectedFiles[i].name,
'base64': this.selectedFilesContent[i]
})
.then(() => {
for_upload--;
if (for_upload == 0) {
this.selectedFiles = [];
this.selectedFilesContent = [];
this.$refs.attachmentNewFiles.value = null;
this.loadReportData();
this.loading = false;
}
});
}
}
},
attachmentDelete(attachment) {
if (!confirm("Naozaj chcete zmazať prilohu?")) return;
this.loading = true;
backend.attachmentDelete(attachment.attachment_id).then(() => {
this.loadReportData();
this.loading = false;
});
},
updateAttachmentContent(event, attachment) {
this.loading = true;
}
if (selectedFiles.length > 0) {
let for_upload = selectedFiles.length;
loading = true;
for (let i = 0; i < selectedFiles.length; i++) {
backend
.attachmentUpdate(attachment.attachment_id, event.target.innerText)
.attachmentAdd(report_id, "file", {
'filename': selectedFiles[i].name,
'base64': selectedFilesContent[i]
})
.then(() => {
this.loadReportData();
this.loading = false;
for_upload--;
if (for_upload == 0) {
selectedFiles = [];
selectedFilesContent = [];
attachmentNewFiles.value = null;
loadReportData();
loading = false;
}
});
},
handleFileUpload(event) {
const files = event.target.files;
if (files) {
for (let i = 0; i < files.length; i++) {
this.selectedFiles.push(files[i]);
const reader = new FileReader();
reader.onload = () => {
this.selectedFilesContent[i] = reader.result;
};
reader.readAsDataURL(files[i]);
}
}
},
removeFile(index) {
this.selectedFiles.splice(index, 1);
this.selectedFilesContent.splice(index, 1);
},
formatFileSize(size) {
if (size < 1024) {
return size + " B";
} else if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + " KB";
} else {
return (size / (1024 * 1024)).toFixed(2) + " MB";
}
},
isImageUrl(url) {
return /\.(jpg|jpeg|png|gif|svg|webp)$/.test(url);
}
},
};
}
}
function attachmentDelete(attachment) {
if (!confirm("Naozaj chcete zmazať prilohu?")) return;
loading = true;
backend.attachmentDelete(attachment.attachment_id).then(() => {
loadReportData();
loading = false;
});
}
function updateAttachmentContent(event, attachment) {
loading = true;
backend
.attachmentUpdate(attachment.attachment_id, event.target.innerText)
.then(() => {
loadReportData();
loading = false;
});
}
function handleFileUpload(event) {
const files = event.target.files;
if (files) {
for (let i = 0; i < files.length; i++) {
selectedFiles.push(files[i]);
const reader = new FileReader();
reader.onload = () => {
selectedFilesContent[i] = reader.result;
};
reader.readAsDataURL(files[i]);
}
}
}
function removeFile(index) {
selectedFiles.splice(index, 1);
selectedFilesContent.splice(index, 1);
}
function formatFileSize(size) {
if (size < 1024) {
return size + " B";
} else if (size < 1024 * 1024) {
return (size / 1024).toFixed(2) + " KB";
} else {
return (size / (1024 * 1024)).toFixed(2) + " MB";
}
}
function isImageUrl(url) {
return /\.(jpg|jpeg|png|gif|svg|webp)$/.test(url);
}
</script>