Renamed error store to notification store, centralized spinner modal
Increased thread pool capacities in `AsyncConfig.java` and adjusted database schema for larger text fields. Enhanced HS code validation logic and added logging to `EUTaxationApiService` for improved traceability. Cleaned up unused error modal code and aligned styles for calculation processing spinners.
This commit is contained in:
parent
5adadb671e
commit
cd66b5bba5
30 changed files with 173 additions and 132 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import {config} from "@/config";
|
import {config} from "@/config";
|
||||||
|
|
||||||
const getCsrfToken = () => {
|
const getCsrfToken = () => {
|
||||||
|
|
@ -141,7 +141,7 @@ function handleErrorResponse(data, requestingStore, request) {
|
||||||
const error = new Error('Internal backend error');
|
const error = new Error('Internal backend error');
|
||||||
error.errorObj = errorObj;
|
error.errorObj = errorObj;
|
||||||
|
|
||||||
const errorStore = useErrorStore();
|
const errorStore = useNotificationStore();
|
||||||
|
|
||||||
if (request.expectedException === null || (Array.isArray(request.expectResponse) && !request.expectedException.includes(data.error.title)) || (typeof request.expectedException === 'string' && data.error.title !== request.expectedException)) {
|
if (request.expectedException === null || (Array.isArray(request.expectResponse) && !request.expectedException.includes(data.error.title)) || (typeof request.expectedException === 'string' && data.error.title !== request.expectedException)) {
|
||||||
logger.error(errorObj, request.expectedException);
|
logger.error(errorObj, request.expectedException);
|
||||||
|
|
@ -170,7 +170,7 @@ const executeRequest = async (requestingStore, request) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.error(error, e);
|
logger.error(error, e);
|
||||||
const errorStore = useErrorStore();
|
const errorStore = useNotificationStore();
|
||||||
void errorStore.addError(error, {store: requestingStore, request: request});
|
void errorStore.addError(error, {store: requestingStore, request: request});
|
||||||
|
|
||||||
throw e;
|
throw e;
|
||||||
|
|
@ -199,7 +199,7 @@ const executeRequest = async (requestingStore, request) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
const errorStore = useErrorStore();
|
const errorStore = useNotificationStore();
|
||||||
void errorStore.addError(error, {store: requestingStore, request: request});
|
void errorStore.addError(error, {store: requestingStore, request: request});
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
|
@ -217,7 +217,7 @@ const executeRequest = async (requestingStore, request) => {
|
||||||
trace: null
|
trace: null
|
||||||
}
|
}
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
const errorStore = useErrorStore();
|
const errorStore = useNotificationStore();
|
||||||
void errorStore.addError(error, {store: requestingStore, request: request});
|
void errorStore.addError(error, {store: requestingStore, request: request});
|
||||||
throw new Error('Internal backend error');
|
throw new Error('Internal backend error');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,54 +1,47 @@
|
||||||
<template>
|
<template>
|
||||||
<teleport to="body">
|
<teleport to="body">
|
||||||
<toast ref="toast"></toast>
|
<toast ref="toast"></toast>
|
||||||
<!-- <transition-->
|
|
||||||
<!-- name="error-container"-->
|
|
||||||
<!-- tag="div"-->
|
<modal :z-index="9000" :state="hasSpinner">
|
||||||
<!-- class="error-notification-container">-->
|
<div class="spinner-box space-around">
|
||||||
<!-- <div class="error-notification" v-if="error">-->
|
<spinner></spinner>
|
||||||
<!-- <div>-->
|
<span>{{ spinnerMsg }}</span>
|
||||||
<!-- <ph-warning size="24"></ph-warning>-->
|
</div>
|
||||||
<!-- </div>-->
|
</modal>
|
||||||
<!-- <div class="error-message">-->
|
|
||||||
<!-- <div class="error-message-title">-->
|
|
||||||
<!-- {{ title }}-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="error-message-content">-->
|
|
||||||
<!-- {{ message }}-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="error-view-trace" v-if="trace" @click="activateTrace">-->
|
|
||||||
<!-- View trace-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <div class="icon-error-notification">-->
|
|
||||||
<!-- <ph-x size="24" @click="close"></ph-x>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- <modal :z-index="9001" :state="showTrace"><trace-view :error="error" @close="deactivateTrace"></trace-view></modal>-->
|
|
||||||
<!-- </div>-->
|
|
||||||
<!-- </transition>-->
|
|
||||||
</teleport>
|
</teleport>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import {mapStores} from "pinia";
|
import {mapStores} from "pinia";
|
||||||
import Toast from "@/components/UI/Toast.vue";
|
import Toast from "@/components/UI/Toast.vue";
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
|
import Box from "@/components/UI/Box.vue";
|
||||||
|
import Spinner from "@/components/UI/Spinner.vue";
|
||||||
|
import Modal from "@/components/UI/Modal.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "TheNotificationSystem",
|
name: "TheNotificationSystem",
|
||||||
components: {Toast},
|
components: {Modal, Spinner, Box, Toast},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useErrorStore),
|
...mapStores(useNotificationStore),
|
||||||
|
hasSpinner() {
|
||||||
|
return this.notificationStore.hasSpinner;
|
||||||
|
},
|
||||||
|
spinnerMsg() {
|
||||||
|
return this.notificationStore.spinnerMsg;
|
||||||
|
},
|
||||||
notifications() {
|
notifications() {
|
||||||
return this.errorStore.notifications;
|
return this.notificationStore.notifications;
|
||||||
},
|
},
|
||||||
hasNotifications() {
|
hasNotifications() {
|
||||||
return this.errorStore.notifications?.length !== 0;
|
return this.notificationStore.notifications?.length !== 0;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
@ -60,7 +53,7 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
fireToasts() {
|
fireToasts() {
|
||||||
while (this.hasNotifications) {
|
while (this.hasNotifications) {
|
||||||
const msg = this.errorStore.popNotification();
|
const msg = this.notificationStore.popNotification();
|
||||||
|
|
||||||
logger.log("fire msg", msg);
|
logger.log("fire msg", msg);
|
||||||
|
|
||||||
|
|
@ -170,4 +163,18 @@ export default {
|
||||||
transition: transform 0.3s ease;
|
transition: transform 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.spinner-box {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 3.6rem;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
font-size: 1.6rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-around {
|
||||||
|
margin: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -182,9 +182,11 @@ export default {
|
||||||
hsCodeChanged(event) {
|
hsCodeChanged(event) {
|
||||||
let sanitized = event.target.value
|
let sanitized = event.target.value
|
||||||
.replace(/\D/g, '')
|
.replace(/\D/g, '')
|
||||||
.substring(0, 10);
|
.substring(0, 10)
|
||||||
|
|
||||||
if(sanitized.length !== 10)
|
if(sanitized.length !== 0)
|
||||||
|
sanitized = sanitized.padEnd(10, '0');
|
||||||
|
else
|
||||||
sanitized = null;
|
sanitized = null;
|
||||||
|
|
||||||
this.$emit("update:hsCode", sanitized);
|
this.$emit("update:hsCode", sanitized);
|
||||||
|
|
|
||||||
|
|
@ -88,7 +88,7 @@ import {buildDate} from "@/common.js";
|
||||||
import BasicButton from "@/components/UI/BasicButton.vue";
|
import BasicButton from "@/components/UI/BasicButton.vue";
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
import {mapStores} from "pinia";
|
import {mapStores} from "pinia";
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "ErrorModalOverview",
|
name: "ErrorModalOverview",
|
||||||
|
|
@ -108,7 +108,7 @@ export default {
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(JSON.stringify(this.error));
|
await navigator.clipboard.writeText(JSON.stringify(this.error));
|
||||||
|
|
||||||
this.errorStore.addNotification({
|
this.notificationStore.addNotification({
|
||||||
icon: 'Clipboard',
|
icon: 'Clipboard',
|
||||||
message: "The error has been copied to clipboard",
|
message: "The error has been copied to clipboard",
|
||||||
title: "Successful copied to clipboard",
|
title: "Successful copied to clipboard",
|
||||||
|
|
@ -120,7 +120,7 @@ export default {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('Fehler beim Kopieren:', err);
|
logger.error('Fehler beim Kopieren:', err);
|
||||||
|
|
||||||
this.errorStore.addNotification({
|
this.notificationStore.addNotification({
|
||||||
icon: 'Clipboard',
|
icon: 'Clipboard',
|
||||||
message: "Cannot copy to clipboard",
|
message: "Cannot copy to clipboard",
|
||||||
title: "Not copied to clipboard",
|
title: "Not copied to clipboard",
|
||||||
|
|
@ -132,7 +132,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useErrorStore),
|
...mapStores(useNotificationStore),
|
||||||
badgeIcon() {
|
badgeIcon() {
|
||||||
if (this.error.type === "FRONTEND") {
|
if (this.error.type === "FRONTEND") {
|
||||||
return "desktop";
|
return "desktop";
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ export default {
|
||||||
},
|
},
|
||||||
formattedBody() {
|
formattedBody() {
|
||||||
if (!this.body) return '[]';
|
if (!this.body) return '[]';
|
||||||
return JSON.stringify(this.body, null, 2);
|
return JSON.stringify(JSON.parse(this.body), null, 2);
|
||||||
},
|
},
|
||||||
formattedHeader() {
|
formattedHeader() {
|
||||||
if (!this.header) return '';
|
if (!this.header) return '';
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import router from './router.js';
|
import router from './router.js';
|
||||||
//import store from './store/index.js';
|
//import store from './store/index.js';
|
||||||
import { setupErrorBuffer } from './store/error.js'
|
import { setupErrorBuffer } from './store/notification.js'
|
||||||
import {createApp} from 'vue'
|
import {createApp} from 'vue'
|
||||||
import {createPinia} from 'pinia';
|
import {createPinia} from 'pinia';
|
||||||
import {startSessionRefresh} from "@/backend.js";
|
import {startSessionRefresh} from "@/backend.js";
|
||||||
|
|
|
||||||
|
|
@ -87,13 +87,14 @@ import {useAssistantStore} from "@/store/assistant.js";
|
||||||
import CreateNewNode from "@/components/layout/node/CreateNewNode.vue";
|
import CreateNewNode from "@/components/layout/node/CreateNewNode.vue";
|
||||||
import Checkbox from "@/components/UI/Checkbox.vue";
|
import Checkbox from "@/components/UI/Checkbox.vue";
|
||||||
import {UrlSafeBase64} from "@/common.js";
|
import {UrlSafeBase64} from "@/common.js";
|
||||||
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "CalculationAssistant",
|
name: "CalculationAssistant",
|
||||||
components: {Checkbox, CreateNewNode, Modal, SupplierItem, MaterialItem, BasicButton, AutosuggestSearchbar},
|
components: {Checkbox, CreateNewNode, Modal, SupplierItem, MaterialItem, BasicButton, AutosuggestSearchbar},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useNodeStore, useAssistantStore),
|
...mapStores(useNodeStore, useAssistantStore, useNotificationStore),
|
||||||
showPartNumberModal() {
|
showPartNumberModal() {
|
||||||
return this.partNumberModalState;
|
return this.partNumberModalState;
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +103,8 @@ export default {
|
||||||
return {
|
return {
|
||||||
newSupplierModalState: false,
|
newSupplierModalState: false,
|
||||||
partNumberModalState: true,
|
partNumberModalState: true,
|
||||||
partNumberField: ''
|
partNumberField: '',
|
||||||
|
createMsg: 'Creating calculations ...'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -111,6 +113,8 @@ export default {
|
||||||
},
|
},
|
||||||
async createPremises() {
|
async createPremises() {
|
||||||
|
|
||||||
|
this.notificationStore.setSpinner(this.createMsg);
|
||||||
|
|
||||||
const ids = await this.assistantStore.createPremises();
|
const ids = await this.assistantStore.createPremises();
|
||||||
|
|
||||||
if (ids.length === 1) {
|
if (ids.length === 1) {
|
||||||
|
|
@ -118,6 +122,9 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.$router.push({name: "bulk", params: {ids: new UrlSafeBase64().encodeIds(ids)}});
|
this.$router.push({name: "bulk", params: {ids: new UrlSafeBase64().encodeIds(ids)}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.notificationStore.clearSpinner();
|
||||||
|
|
||||||
this.assistantStore.reset();
|
this.assistantStore.reset();
|
||||||
},
|
},
|
||||||
selectedSupplier(supplier) {
|
selectedSupplier(supplier) {
|
||||||
|
|
|
||||||
|
|
@ -53,14 +53,6 @@
|
||||||
</transition-group>
|
</transition-group>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
||||||
|
|
||||||
<modal :z-index="3000" :state="showProcessingModal">
|
|
||||||
<div class="edit-calculation-spinner-container space-around">
|
|
||||||
<spinner></spinner>
|
|
||||||
<span>{{ shownProcessingMessage }}</span>
|
|
||||||
</div>
|
|
||||||
</modal>
|
|
||||||
|
|
||||||
<mass-edit-dialog v-if="showData" :show="showMultiselectAction" @action="multiselectAction"
|
<mass-edit-dialog v-if="showData" :show="showMultiselectAction" @action="multiselectAction"
|
||||||
:select-count="selectCount"></mass-edit-dialog>
|
:select-count="selectCount"></mass-edit-dialog>
|
||||||
|
|
||||||
|
|
@ -124,6 +116,7 @@ import DestinationListView from "@/components/layout/edit/DestinationListView.vu
|
||||||
import Toast from "@/components/UI/Toast.vue";
|
import Toast from "@/components/UI/Toast.vue";
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
import {useCustomsStore} from "@/store/customs.js";
|
import {useCustomsStore} from "@/store/customs.js";
|
||||||
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
|
|
||||||
|
|
||||||
const COMPONENT_TYPES = {
|
const COMPONENT_TYPES = {
|
||||||
|
|
@ -147,7 +140,7 @@ export default {
|
||||||
BasicButton
|
BasicButton
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(usePremiseEditStore, useCustomsStore),
|
...mapStores(usePremiseEditStore, useCustomsStore, useNotificationStore),
|
||||||
hasSelection() {
|
hasSelection() {
|
||||||
if (this.premiseEditStore.isLoading || this.premiseEditStore.selectedLoading) {
|
if (this.premiseEditStore.isLoading || this.premiseEditStore.selectedLoading) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -191,14 +184,20 @@ export default {
|
||||||
return this.modalType ? this.componentsData[this.modalType] : null;
|
return this.modalType ? this.componentsData[this.modalType] : null;
|
||||||
},
|
},
|
||||||
showProcessingModal() {
|
showProcessingModal() {
|
||||||
return this.premiseEditStore.showProcessingModal || this.showCalculationModal || this.customsStore.loadingTariff;
|
return this.premiseEditStore.showProcessingModal || this.showCalculationModal;
|
||||||
},
|
},
|
||||||
shownProcessingMessage() {
|
shownProcessingMessage() {
|
||||||
if(this.customsStore.loadingTariff)
|
|
||||||
return "Looking up tariff rate ..."
|
|
||||||
|
|
||||||
return this.processingMessage;
|
return this.processingMessage;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
showProcessingModal(newState, _) {
|
||||||
|
if(newState) {
|
||||||
|
this.notificationStore.setSpinner(this.shownProcessingMessage);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.notificationStore.clearSpinner();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
|
@ -521,7 +520,7 @@ export default {
|
||||||
flex: 1 1 30rem
|
flex: 1 1 30rem
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-calculation-spinner {
|
.spinner-box {
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
width: 24rem;
|
width: 24rem;
|
||||||
height: 12rem;
|
height: 12rem;
|
||||||
|
|
|
||||||
|
|
@ -19,12 +19,12 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="premiseSingleEditStore.showLoadingSpinner" class="edit-calculation-spinner-container">
|
<div v-if="premiseSingleEditStore.showLoadingSpinner" class="edit-calculation-spinner-container">
|
||||||
<box class="edit-calculation-spinner">
|
<box class="spinner-box">
|
||||||
<spinner></spinner>
|
<spinner></spinner>
|
||||||
</box>
|
</box>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="premiseSingleEditStore.isEmpty" class="edit-calculation-spinner-container">
|
<div v-else-if="premiseSingleEditStore.isEmpty" class="edit-calculation-spinner-container">
|
||||||
<box class="edit-calculation-spinner">No calculation found.</box>
|
<box class="spinner-box">No calculation found.</box>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
|
|
||||||
|
|
@ -85,13 +85,6 @@
|
||||||
<h3 class="sub-header">Destinations & routes</h3>
|
<h3 class="sub-header">Destinations & routes</h3>
|
||||||
<destination-list-view></destination-list-view>
|
<destination-list-view></destination-list-view>
|
||||||
|
|
||||||
<modal :z-index="3000" :state="showProcessingModal">
|
|
||||||
<div class="edit-calculation-spinner-container space-around">
|
|
||||||
<spinner></spinner>
|
|
||||||
<span>{{ shownProcessingMessage }}</span>
|
|
||||||
</div>
|
|
||||||
</modal>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -106,24 +99,24 @@ import PackagingEdit from "@/components/layout/edit/PackagingEdit.vue";
|
||||||
import PriceEdit from "@/components/layout/edit/PriceEdit.vue";
|
import PriceEdit from "@/components/layout/edit/PriceEdit.vue";
|
||||||
import DestinationListView from "@/components/layout/edit/DestinationListView.vue";
|
import DestinationListView from "@/components/layout/edit/DestinationListView.vue";
|
||||||
import {mapStores} from "pinia";
|
import {mapStores} from "pinia";
|
||||||
import Spinner from "@/components/UI/Spinner.vue";
|
|
||||||
import NotificationBar from "@/components/UI/NotificationBar.vue";
|
import NotificationBar from "@/components/UI/NotificationBar.vue";
|
||||||
import Modal from "@/components/UI/Modal.vue";
|
import Modal from "@/components/UI/Modal.vue";
|
||||||
import TraceView from "@/components/layout/TraceView.vue";
|
import TraceView from "@/components/layout/TraceView.vue";
|
||||||
import IconButton from "@/components/UI/IconButton.vue";
|
import IconButton from "@/components/UI/IconButton.vue";
|
||||||
import {UrlSafeBase64} from "@/common.js";
|
import {UrlSafeBase64} from "@/common.js";
|
||||||
import {usePremiseSingleEditStore} from "@/store/premiseSingleEdit.js";
|
import {usePremiseSingleEditStore} from "@/store/premiseSingleEdit.js";
|
||||||
import logger from "@/logger.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
|
import Spinner from "@/components/UI/Spinner.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "SingleEdit",
|
name: "SingleEdit",
|
||||||
components: {
|
components: {
|
||||||
|
Spinner,
|
||||||
|
|
||||||
IconButton,
|
IconButton,
|
||||||
TraceView,
|
TraceView,
|
||||||
Modal,
|
Modal,
|
||||||
NotificationBar,
|
NotificationBar,
|
||||||
Spinner,
|
|
||||||
DestinationListView,
|
DestinationListView,
|
||||||
PriceEdit,
|
PriceEdit,
|
||||||
PackagingEdit,
|
PackagingEdit,
|
||||||
|
|
@ -137,11 +130,10 @@ export default {
|
||||||
traceModal: false,
|
traceModal: false,
|
||||||
bulkEditQuery: null,
|
bulkEditQuery: null,
|
||||||
id: null,
|
id: null,
|
||||||
showCalculationModal: false,
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(usePremiseSingleEditStore),
|
...mapStores(usePremiseSingleEditStore, useNotificationStore),
|
||||||
premise() {
|
premise() {
|
||||||
return this.premiseSingleEditStore.premise;
|
return this.premiseSingleEditStore.premise;
|
||||||
},
|
},
|
||||||
|
|
@ -149,7 +141,7 @@ export default {
|
||||||
return this.bulkEditQuery !== null;
|
return this.bulkEditQuery !== null;
|
||||||
},
|
},
|
||||||
showProcessingModal() {
|
showProcessingModal() {
|
||||||
return this.premiseSingleEditStore.showProcessingModal || this.showCalculationModal;
|
return this.premiseSingleEditStore.showProcessingModal;
|
||||||
},
|
},
|
||||||
shownProcessingMessage() {
|
shownProcessingMessage() {
|
||||||
if (this.premiseSingleEditStore.routing)
|
if (this.premiseSingleEditStore.routing)
|
||||||
|
|
@ -158,6 +150,16 @@ export default {
|
||||||
return "Please wait. Calculating ...";
|
return "Please wait. Calculating ...";
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
showProcessingModal(newState, _) {
|
||||||
|
if(newState) {
|
||||||
|
this.notificationStore.setSpinner(this.shownProcessingMessage);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.notificationStore.clearSpinner();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
async startCalculation() {
|
async startCalculation() {
|
||||||
|
|
@ -275,17 +277,7 @@ export default {
|
||||||
margin: 3rem;
|
margin: 3rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.edit-calculation-spinner-container {
|
.spinner-box {
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
gap: 3.6rem;
|
|
||||||
flex: 1 1 auto;
|
|
||||||
font-size: 1.6rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.edit-calculation-spinner {
|
|
||||||
font-size: 1.6rem;
|
font-size: 1.6rem;
|
||||||
width: 24rem;
|
width: 24rem;
|
||||||
height: 12rem;
|
height: 12rem;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest, {performDownload, performUpload} from "@/backend.js";
|
import performRequest, {performDownload, performUpload} from "@/backend.js";
|
||||||
|
|
||||||
export const useBulkOperationStore = defineStore('bulkOperation', {
|
export const useBulkOperationStore = defineStore('bulkOperation', {
|
||||||
|
|
@ -39,6 +39,14 @@ export const useBulkOperationStore = defineStore('bulkOperation', {
|
||||||
|
|
||||||
this.stopTimer();
|
this.stopTimer();
|
||||||
|
|
||||||
|
if(!restart)
|
||||||
|
useNotificationStore().addNotification({
|
||||||
|
title: 'Bulk operation',
|
||||||
|
message: 'All your bulk operations have been completed.',
|
||||||
|
type: 'success',
|
||||||
|
icon: 'stack',
|
||||||
|
})
|
||||||
|
|
||||||
if(restart) {
|
if(restart) {
|
||||||
this.startTimer();
|
this.startTimer();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
||||||
export const useContainerRateStore = defineStore('containerRate', {
|
export const useContainerRateStore = defineStore('containerRate', {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import {useStageStore} from "@/store/stage.js";
|
import {useStageStore} from "@/store/stage.js";
|
||||||
import {usePropertySetsStore} from "@/store/propertySets.js";
|
import {usePropertySetsStore} from "@/store/propertySets.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
||||||
export const useMatrixRateStore = defineStore('matrixRate', {
|
export const useMatrixRateStore = defineStore('matrixRate', {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,22 +4,30 @@ import {toRaw} from "vue";
|
||||||
import {getCsrfToken} from "@/backend.js";
|
import {getCsrfToken} from "@/backend.js";
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
|
|
||||||
export const useErrorStore = defineStore('error', {
|
export const useNotificationStore = defineStore('notification', {
|
||||||
state() {
|
state() {
|
||||||
return {
|
return {
|
||||||
notifications: [],
|
notifications: [],
|
||||||
sendCache: [],
|
sendCache: [],
|
||||||
autoSubmitInterval: 30000,
|
autoSubmitInterval: 30000,
|
||||||
autoSubmitTimer: null
|
autoSubmitTimer: null,
|
||||||
|
spinnerMessage: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getters: {
|
getters: {
|
||||||
lastError: (state) => state.notifications.length > 0 ? state.notifications[state.notifications.length - 1].error : null,
|
hasSpinner(state) {
|
||||||
|
return state.spinnerMessage !== null;
|
||||||
|
},
|
||||||
|
spinnerMsg(state) {
|
||||||
|
return state.spinnerMessage;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
clearErrors() {
|
setSpinner(msg) {
|
||||||
this.notifications = [];
|
this.spinnerMessage = msg;
|
||||||
console.log("Cleared errors");
|
},
|
||||||
|
clearSpinner() {
|
||||||
|
this.spinnerMessage = null;
|
||||||
},
|
},
|
||||||
popNotification() {
|
popNotification() {
|
||||||
return this.notifications.pop();
|
return this.notifications.pop();
|
||||||
|
|
@ -118,7 +126,7 @@ export const useErrorStore = defineStore('error', {
|
||||||
const pinia = this.$pinia || getActivePinia()
|
const pinia = this.$pinia || getActivePinia()
|
||||||
if (pinia && pinia._s) {
|
if (pinia && pinia._s) {
|
||||||
pinia._s.forEach((store, storeId) => {
|
pinia._s.forEach((store, storeId) => {
|
||||||
if (storeId !== 'error' && store.$state) {
|
if (storeId !== 'error' && storeId !== 'errorLog' && store.$state) {
|
||||||
storeState[storeId] = {
|
storeState[storeId] = {
|
||||||
...toRaw(store.$state)
|
...toRaw(store.$state)
|
||||||
}
|
}
|
||||||
|
|
@ -147,20 +155,20 @@ export const useErrorStore = defineStore('error', {
|
||||||
|
|
||||||
// Global Error Handler Setup
|
// Global Error Handler Setup
|
||||||
export function setupErrorBuffer() {
|
export function setupErrorBuffer() {
|
||||||
const errorStore = useErrorStore()
|
const errorStore = useNotificationStore()
|
||||||
|
|
||||||
//Unhandled Promise Rejections
|
//Unhandled Promise Rejections
|
||||||
window.addEventListener('unhandledrejection', (event) => {
|
// window.addEventListener('unhandledrejection', (event) => {
|
||||||
|
//
|
||||||
const error = {
|
// const error = {
|
||||||
code: "Unhandled rejection",
|
// code: "Unhandled rejection",
|
||||||
title: "Frontend error",
|
// title: "Frontend error",
|
||||||
message: event.reason?.message || 'Unhandled Promise Rejection',
|
// message: event.reason?.message || 'Unhandled Promise Rejection',
|
||||||
traceCombined: event.reason?.stack,
|
// traceCombined: event.reason?.stack,
|
||||||
};
|
// };
|
||||||
|
//
|
||||||
errorStore.addError(error, {global: true}).then(r => {} );
|
// errorStore.addError(error, {global: true}).then(r => {} );
|
||||||
})
|
// })
|
||||||
|
|
||||||
// // JavaScript Errors
|
// // JavaScript Errors
|
||||||
window.addEventListener('error', (event) => {
|
window.addEventListener('error', (event) => {
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
import logger from "@/logger.js";
|
import logger from "@/logger.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {toRaw} from "vue";
|
import {toRaw} from "vue";
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import logger from "@/logger.js"
|
import logger from "@/logger.js"
|
||||||
import performRequest from '@/backend.js'
|
import performRequest from '@/backend.js'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import { useStageStore } from './stage.js'
|
import { useStageStore } from './stage.js'
|
||||||
import {usePropertySetsStore} from "@/store/propertySets.js";
|
import {usePropertySetsStore} from "@/store/propertySets.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import { useStageStore } from './stage.js'
|
import { useStageStore } from './stage.js'
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
||||||
export const useStageStore = defineStore('stage', {
|
export const useStageStore = defineStore('stage', {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
||||||
export const useStagedRatesStore = defineStore('stagedRates', {
|
export const useStagedRatesStore = defineStore('stagedRates', {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import {defineStore} from 'pinia'
|
import {defineStore} from 'pinia'
|
||||||
import {config} from '@/config'
|
import {config} from '@/config'
|
||||||
import {useErrorStore} from "@/store/error.js";
|
import {useNotificationStore} from "@/store/notification.js";
|
||||||
import { useStageStore } from './stage.js'
|
import { useStageStore } from './stage.js'
|
||||||
import performRequest from "@/backend.js";
|
import performRequest from "@/backend.js";
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,9 +16,9 @@ public class AsyncConfig {
|
||||||
@Bean(name = "calculationExecutor")
|
@Bean(name = "calculationExecutor")
|
||||||
public Executor taskExecutor() {
|
public Executor taskExecutor() {
|
||||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
executor.setCorePoolSize(4);
|
executor.setCorePoolSize(16);
|
||||||
executor.setMaxPoolSize(8);
|
executor.setMaxPoolSize(32);
|
||||||
executor.setQueueCapacity(100);
|
executor.setQueueCapacity(500);
|
||||||
executor.setThreadNamePrefix("calc-");
|
executor.setThreadNamePrefix("calc-");
|
||||||
executor.initialize();
|
executor.initialize();
|
||||||
return executor;
|
return executor;
|
||||||
|
|
@ -27,9 +27,9 @@ public class AsyncConfig {
|
||||||
@Bean(name = "customLookupExecutor")
|
@Bean(name = "customLookupExecutor")
|
||||||
public Executor customLookupExecutor() {
|
public Executor customLookupExecutor() {
|
||||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
executor.setCorePoolSize(4);
|
executor.setCorePoolSize(16);
|
||||||
executor.setMaxPoolSize(8);
|
executor.setMaxPoolSize(32);
|
||||||
executor.setQueueCapacity(100);
|
executor.setQueueCapacity(500);
|
||||||
executor.setThreadNamePrefix("lookup-");
|
executor.setThreadNamePrefix("lookup-");
|
||||||
executor.initialize();
|
executor.initialize();
|
||||||
return executor;
|
return executor;
|
||||||
|
|
@ -40,7 +40,7 @@ public class AsyncConfig {
|
||||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||||
executor.setCorePoolSize(1);
|
executor.setCorePoolSize(1);
|
||||||
executor.setMaxPoolSize(1);
|
executor.setMaxPoolSize(1);
|
||||||
executor.setQueueCapacity(100);
|
executor.setQueueCapacity(500);
|
||||||
executor.setThreadNamePrefix("bulk-");
|
executor.setThreadNamePrefix("bulk-");
|
||||||
|
|
||||||
executor.setWaitForTasksToCompleteOnShutdown(true);
|
executor.setWaitForTasksToCompleteOnShutdown(true);
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package de.avatic.lcc.service.api;
|
||||||
|
|
||||||
import eu.europa.ec.taxation.taric.client.*;
|
import eu.europa.ec.taxation.taric.client.*;
|
||||||
import jakarta.xml.bind.JAXBElement;
|
import jakarta.xml.bind.JAXBElement;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Async;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.ws.client.core.WebServiceTemplate;
|
import org.springframework.ws.client.core.WebServiceTemplate;
|
||||||
|
|
@ -17,6 +19,7 @@ public class EUTaxationApiService {
|
||||||
|
|
||||||
private final WebServiceTemplate webServiceTemplate;
|
private final WebServiceTemplate webServiceTemplate;
|
||||||
private final ObjectFactory objectFactory;
|
private final ObjectFactory objectFactory;
|
||||||
|
private Logger logger = LoggerFactory.getLogger(EUTaxationApiService.class);
|
||||||
|
|
||||||
public EUTaxationApiService(WebServiceTemplate webServiceTemplate) {
|
public EUTaxationApiService(WebServiceTemplate webServiceTemplate) {
|
||||||
this.webServiceTemplate = webServiceTemplate;
|
this.webServiceTemplate = webServiceTemplate;
|
||||||
|
|
@ -25,6 +28,9 @@ public class EUTaxationApiService {
|
||||||
|
|
||||||
@Async("customLookupExecutor")
|
@Async("customLookupExecutor")
|
||||||
public CompletableFuture<GoodsDescrForWsResponse> getGoodsDescription(String goodsCode, String languageCode) {
|
public CompletableFuture<GoodsDescrForWsResponse> getGoodsDescription(String goodsCode, String languageCode) {
|
||||||
|
|
||||||
|
logger.info("Start lookup for {} and {}", goodsCode, languageCode);
|
||||||
|
|
||||||
GoodsDescrForWs request = new GoodsDescrForWs();
|
GoodsDescrForWs request = new GoodsDescrForWs();
|
||||||
request.setGoodsCode(goodsCode);
|
request.setGoodsCode(goodsCode);
|
||||||
request.setLanguageCode(languageCode);
|
request.setLanguageCode(languageCode);
|
||||||
|
|
@ -64,4 +70,12 @@ public class EUTaxationApiService {
|
||||||
throw new RuntimeException("Fehler beim Erstellen des Datums", e);
|
throw new RuntimeException("Fehler beim Erstellen des Datums", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Logger getLogger() {
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLogger(Logger logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -325,6 +325,10 @@ public class PreCalculationCheckService {
|
||||||
|
|
||||||
private void materialCheck(Premise premise) {
|
private void materialCheck(Premise premise) {
|
||||||
|
|
||||||
|
if(premise.getHsCode() == null || premise.getHsCode().length() < 10)
|
||||||
|
throw new PremiseValidationError("Invalid HS code.");
|
||||||
|
|
||||||
|
|
||||||
var isDeclarable = eUTaxationResolverService.validate(premise.getHsCode());
|
var isDeclarable = eUTaxationResolverService.validate(premise.getHsCode());
|
||||||
|
|
||||||
if (!isDeclarable)
|
if (!isDeclarable)
|
||||||
|
|
|
||||||
|
|
@ -637,8 +637,8 @@ CREATE TABLE IF NOT EXISTS sys_error
|
||||||
title VARCHAR(255) NOT NULL,
|
title VARCHAR(255) NOT NULL,
|
||||||
code VARCHAR(255) NOT NULL,
|
code VARCHAR(255) NOT NULL,
|
||||||
message VARCHAR(1024) NOT NULL,
|
message VARCHAR(1024) NOT NULL,
|
||||||
request TEXT,
|
request MEDIUMTEXT,
|
||||||
pinia TEXT,
|
pinia MEDIUMTEXT,
|
||||||
calculation_job_id INT DEFAULT NULL,
|
calculation_job_id INT DEFAULT NULL,
|
||||||
bulk_operation_id INT DEFAULT NULL,
|
bulk_operation_id INT DEFAULT NULL,
|
||||||
type CHAR(16) NOT NULL DEFAULT 'BACKEND',
|
type CHAR(16) NOT NULL DEFAULT 'BACKEND',
|
||||||
|
|
|
||||||
|
|
@ -637,8 +637,8 @@ CREATE TABLE IF NOT EXISTS sys_error
|
||||||
title VARCHAR(255) NOT NULL,
|
title VARCHAR(255) NOT NULL,
|
||||||
code VARCHAR(255) NOT NULL,
|
code VARCHAR(255) NOT NULL,
|
||||||
message VARCHAR(1024) NOT NULL,
|
message VARCHAR(1024) NOT NULL,
|
||||||
request TEXT,
|
request MEDIUMTEXT,
|
||||||
pinia TEXT,
|
pinia MEDIUMTEXT,
|
||||||
calculation_job_id INT DEFAULT NULL,
|
calculation_job_id INT DEFAULT NULL,
|
||||||
bulk_operation_id INT DEFAULT NULL,
|
bulk_operation_id INT DEFAULT NULL,
|
||||||
type CHAR(16) NOT NULL DEFAULT 'BACKEND',
|
type CHAR(16) NOT NULL DEFAULT 'BACKEND',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue