diff --git a/src/frontend/src/components/UI/TreeNode.vue b/src/frontend/src/components/UI/TreeNode.vue
index 91c9804..10ae520 100644
--- a/src/frontend/src/components/UI/TreeNode.vue
+++ b/src/frontend/src/components/UI/TreeNode.vue
@@ -63,7 +63,7 @@ export default {
expanded: {
type: Boolean,
default: false
- }
+ },
},
data() {
return {
@@ -79,12 +79,11 @@ export default {
},
displayKey() {
if (this.keyName === 'root') return 'JSON'
- return Array.isArray(this.parentData) ? `[${this.keyName}]` : this.keyName
+ return this.keyName
},
keyClass() {
return {
- 'array-index': Array.isArray(this.parentData),
- 'object-key': !Array.isArray(this.parentData),
+ 'object-key': this.keyName !== 'root',
'root-key': this.keyName === 'root'
}
},
diff --git a/src/frontend/src/components/layout/config/BulkOperations.vue b/src/frontend/src/components/layout/config/BulkOperations.vue
index a2bb5f0..9e1a614 100644
--- a/src/frontend/src/components/layout/config/BulkOperations.vue
+++ b/src/frontend/src/components/layout/config/BulkOperations.vue
@@ -26,13 +26,13 @@
validity period
@@ -77,11 +77,11 @@
-
+
No recent bulk operations
-
+
@@ -112,6 +112,7 @@ export default {
importDataset: "NODE",
selectedFileName: null,
selectedFile: null,
+ fileBlob: null,
uploading: false,
processId: null,
}
@@ -126,7 +127,7 @@ export default {
async isSelected(newVal) {
if(newVal === true)
await this.validityPeriodStore.loadPeriods();
- await this.bulkOperationStore.manageStatus();
+ await this.bulkOperationStore.manageStatus();
}
},
computed: {
@@ -166,7 +167,7 @@ export default {
}
},
methods: {
- buildDate(date) {
+ buildDate(date) {
return `${date[0]}-${date[1].toString().padStart(2, '0')}-${date[2].toString().padStart(2, '0')} ${date[3].toString().padStart(2, '0')}:${date[4].toString().padStart(2, '0')}:${date[5].toString().padStart(2, '0')}`
},
async fetchFile(id) {
@@ -183,22 +184,60 @@ export default {
await this.bulkOperationStore.scheduleDownload(this.exportDataset, isCurrent ? null : this.selectedPeriod);
}
},
- inputFile(event) {
+ async inputFile(event) {
const file = event.target.files[0];
if (file) {
- this.selectedFile = file;
- this.selectedFileName = file.name;
+ try {
+ // Datei sofort in den RAM laden als Blob
+ this.fileBlob = await this.readFileAsBlob(file);
+
+ // File-Objekt mit dem Blob erstellen, das den originalen Namen und Typ behält
+ this.selectedFile = new File([this.fileBlob], file.name, { type: file.type });
+ this.selectedFileName = file.name;
+
+ logger.info(`File loaded into memory: ${file.name} (${(file.size / 1024).toFixed(2)} KB)`);
+ } catch (error) {
+ logger.error('Error reading file:', error);
+ this.selectedFile = null;
+ this.selectedFileName = null;
+ this.fileBlob = null;
+ }
} else {
this.selectedFile = null;
this.selectedFileName = null;
+ this.fileBlob = null;
}
+
+ // Input zurücksetzen, damit dieselbe Datei erneut ausgewählt werden kann
+ event.target.value = '';
+ },
+ readFileAsBlob(file) {
+ return new Promise((resolve, reject) => {
+ const reader = new FileReader();
+
+ reader.onload = (e) => {
+ // ArrayBuffer in Blob konvertieren
+ const blob = new Blob([e.target.result], { type: file.type });
+ resolve(blob);
+ };
+
+ reader.onerror = (error) => {
+ reject(error);
+ };
+
+ // Datei als ArrayBuffer lesen
+ reader.readAsArrayBuffer(file);
+ });
},
async uploadFile() {
if (!this.selectedFile)
return;
- await this.bulkOperationStore.scheduleUpload(this.importDataset, this.selectedFile);
+ const file = this.selectedFile;
+ this.selectedFile = null;
+ this.selectedFileName = null;
+ await this.bulkOperationStore.scheduleUpload(this.importDataset, file);
}
}
}
diff --git a/src/frontend/src/pages/CalcualtionDump.vue b/src/frontend/src/pages/CalcualtionDump.vue
index 194aa1a..78a4f57 100644
--- a/src/frontend/src/pages/CalcualtionDump.vue
+++ b/src/frontend/src/pages/CalcualtionDump.vue
@@ -1,15 +1,20 @@
+
+
-
-
- {{ expand === true ? 'Collapse all items' : 'Expand all items' }}
-
-
-
+
+
+
+ {{ expand === true ? 'Collapse all items' : 'Expand all items' }}
+
+
+
+
+
diff --git a/src/frontend/src/pages/Calculations.vue b/src/frontend/src/pages/Calculations.vue
index ef20c9d..2a13e83 100644
--- a/src/frontend/src/pages/Calculations.vue
+++ b/src/frontend/src/pages/Calculations.vue
@@ -97,7 +97,7 @@ export default {
if (ids.length === 1) {
this.$router.push({name: "edit", params: {id: new UrlSafeBase64().encodeIds([ids[0]])}});
- } else {
+ } else if(ids.length !== 0) {
this.$router.push({name: "bulk", params: {ids: new UrlSafeBase64().encodeIds(ids)}});
}
diff --git a/src/main/java/de/avatic/lcc/dto/bulk/BulkFileType.java b/src/main/java/de/avatic/lcc/dto/bulk/BulkFileType.java
index 5ac102b..c55edf7 100644
--- a/src/main/java/de/avatic/lcc/dto/bulk/BulkFileType.java
+++ b/src/main/java/de/avatic/lcc/dto/bulk/BulkFileType.java
@@ -1,5 +1,16 @@
package de.avatic.lcc.dto.bulk;
public enum BulkFileType {
- CONTAINER_RATE, COUNTRY_MATRIX, MATERIAL, PACKAGING, NODE
+ CONTAINER_RATE("container rate"), COUNTRY_MATRIX("kilometer rate"), MATERIAL("material"), PACKAGING("packaging"), NODE("node");
+
+ private final String fileType;
+
+ BulkFileType(String fileType) {
+ this.fileType = fileType;
+ }
+
+
+ public String getFileType() {
+ return fileType;
+ }
}
diff --git a/src/main/java/de/avatic/lcc/repositories/rates/ContainerRateRepository.java b/src/main/java/de/avatic/lcc/repositories/rates/ContainerRateRepository.java
index 149227c..9c38f2c 100644
--- a/src/main/java/de/avatic/lcc/repositories/rates/ContainerRateRepository.java
+++ b/src/main/java/de/avatic/lcc/repositories/rates/ContainerRateRepository.java
@@ -224,6 +224,12 @@ public class ContainerRateRepository {
nodeId, nodeId, TransportType.SEA.name(), TransportType.RAIL.name()));
}
+ @Transactional
+ public void clearDraft() {
+ var sql = "DELETE FROM container_rate WHERE container_rate.validity_period_id = (SELECT id FROM validity_period WHERE state = ?)";
+ jdbcTemplate.update(sql, ValidityPeriodState.DRAFT.name());
+ }
+
private static class ContainerRateMapper implements RowMapper {
diff --git a/src/main/java/de/avatic/lcc/service/bulk/BulkImportService.java b/src/main/java/de/avatic/lcc/service/bulk/BulkImportService.java
index 4ec0a45..8dba972 100644
--- a/src/main/java/de/avatic/lcc/service/bulk/BulkImportService.java
+++ b/src/main/java/de/avatic/lcc/service/bulk/BulkImportService.java
@@ -59,7 +59,7 @@ public class BulkImportService {
Sheet sheet = workbook.getSheet(BulkFileTypes.valueOf(type.name()).getSheetName());
if(sheet == null)
- throw new ExcelValidationError("Provided file does not contain a sheet named " + BulkFileTypes.valueOf(type.name()).getSheetName());
+ throw new ExcelValidationError("Unable to import " + op.getFileType().getFileType() + ", because \"" + BulkFileTypes.valueOf(type.name()).getSheetName() + "\" sheet is missing. Please use correct template.");
switch (type) {
diff --git a/src/main/java/de/avatic/lcc/service/bulk/bulkImport/ContainerRateImportService.java b/src/main/java/de/avatic/lcc/service/bulk/bulkImport/ContainerRateImportService.java
index 8a0de68..97cb070 100644
--- a/src/main/java/de/avatic/lcc/service/bulk/bulkImport/ContainerRateImportService.java
+++ b/src/main/java/de/avatic/lcc/service/bulk/bulkImport/ContainerRateImportService.java
@@ -20,6 +20,7 @@ public class ContainerRateImportService {
public void processContainerRates(List containerRates) {
Integer periodId = validityPeriodRepository.getDraftPeriodId();
+ containerRateRepository.clearDraft();
containerRates.forEach(rate -> processContainerRate(rate,periodId));
}