Add CalculationDumps component and API controller for dump management in Config page
This commit is contained in:
parent
726dfd63bd
commit
f1222dc410
9 changed files with 197 additions and 35 deletions
|
|
@ -66,13 +66,10 @@ export default {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.tree-container {
|
.tree-container {
|
||||||
|
|
||||||
backdrop-filter: blur(10px);
|
backdrop-filter: blur(10px);
|
||||||
|
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
/* Remove any fixed height constraints */
|
height: 100%; /* Nimmt die volle Höhe des Parent-Containers */
|
||||||
min-height: fit-content;
|
max-height: 100%; /* Verhindert Überlauf */
|
||||||
height: auto;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tree-container::-webkit-scrollbar {
|
.tree-container::-webkit-scrollbar {
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,6 @@ export default {
|
||||||
|
|
||||||
.apps-container {
|
.apps-container {
|
||||||
padding: 2.4rem;
|
padding: 2.4rem;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app-list-header {
|
.app-list-header {
|
||||||
|
|
|
||||||
146
src/frontend/src/components/layout/config/CalculationDumps.vue
Normal file
146
src/frontend/src/components/layout/config/CalculationDumps.vue
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
<template>
|
||||||
|
<div class="dump-container">
|
||||||
|
|
||||||
|
<table-view :columns="columns" :data-source="fetch" :page-size="pageSize" :page="pagination.page"
|
||||||
|
:page-count="pagination.pageCount" :total-count="pagination.totalCount" @row-click="showDump"
|
||||||
|
:mouse-over="true"></table-view>
|
||||||
|
|
||||||
|
|
||||||
|
<modal :state="showModal">
|
||||||
|
<div class="single-dump-container">
|
||||||
|
<div class="button-container">
|
||||||
|
<basic-button @click="showModal = false" :show-icon="false" variant="secondary">Close</basic-button>
|
||||||
|
</div>
|
||||||
|
<json-tree-viewer :data="dump" :all-expanded="expand"></json-tree-viewer>
|
||||||
|
</div>
|
||||||
|
</modal>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import TableView from "@/components/UI/TableView.vue";
|
||||||
|
import performRequest from "@/backend.js";
|
||||||
|
import {config} from "@/config.js";
|
||||||
|
import Modal from "@/components/UI/Modal.vue";
|
||||||
|
import JsonTreeViewer from "@/components/UI/JsonTreeViewer.vue";
|
||||||
|
import BasicButton from "@/components/UI/BasicButton.vue";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "CalculationDumps",
|
||||||
|
components: {BasicButton, JsonTreeViewer, Modal, TableView},
|
||||||
|
methods: {
|
||||||
|
showDump(dump) {
|
||||||
|
this.dump = dump;
|
||||||
|
this.showModal = true;
|
||||||
|
},
|
||||||
|
async fetch(query) {
|
||||||
|
|
||||||
|
const params = new URLSearchParams();
|
||||||
|
if (query?.searchTerm && query.searchTerm !== '')
|
||||||
|
params.append('filter', query.searchTerm);
|
||||||
|
if (query?.periodId)
|
||||||
|
params.append('valid', query.periodId);
|
||||||
|
|
||||||
|
if (query?.page)
|
||||||
|
params.append('page', query.page);
|
||||||
|
|
||||||
|
if (query?.pageSize)
|
||||||
|
params.append('limit', query.pageSize);
|
||||||
|
|
||||||
|
const resp = await performRequest(null, "GET", `${config.backendUrl}/dumps/dump/${params.size === 0 ? '' : '?'}${params.toString()}`, null);
|
||||||
|
this.dump = resp.data;
|
||||||
|
this.pagination = {
|
||||||
|
page: parseInt(resp.headers.get('X-Current-Page')),
|
||||||
|
pageCount: parseInt(resp.headers.get('X-Page-Count')),
|
||||||
|
totalCount: parseInt(resp.headers.get('X-Total-Count'))
|
||||||
|
};
|
||||||
|
|
||||||
|
return this.dump;
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showModal: false,
|
||||||
|
dump: null,
|
||||||
|
|
||||||
|
pageSize: 20,
|
||||||
|
pagination: {page: 1, pageCount: 1, totalCount: 1},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
key: 'id',
|
||||||
|
label: 'ID',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'calculation_date',
|
||||||
|
label: 'Calculation date',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'job_state',
|
||||||
|
label: 'State',
|
||||||
|
badgeResolver: (value) => {
|
||||||
|
if (value === 'VALID')
|
||||||
|
return [{text: value, variant: "primary"}];
|
||||||
|
if (value === 'EXCEPTION')
|
||||||
|
return [{text: value, variant: "exception"}]
|
||||||
|
return [{text: value, variant: "secondary"}]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'user_id',
|
||||||
|
label: 'User ID',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'premise.material.part_number',
|
||||||
|
label: 'Material',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'premise.supplier.name',
|
||||||
|
label: 'Supplier',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'premise.destinations',
|
||||||
|
label: 'Destinations',
|
||||||
|
formatter: (value) => {
|
||||||
|
return value.map(v => v.destination_node.name).join(', ');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dump-container {
|
||||||
|
padding: 2.4rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-dump-container {
|
||||||
|
height: 80vh;
|
||||||
|
width: 80vw;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-dump-container > :first-child {
|
||||||
|
flex-shrink: 0; /* Button behält seine Größe */
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-dump-container > :last-child {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0; /* Wichtig für Flex-Children mit overflow */
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
@ -35,7 +35,7 @@ export default {
|
||||||
components: {Box, BasicButton, ToggleSwitch, JsonTreeViewer},
|
components: {Box, BasicButton, ToggleSwitch, JsonTreeViewer},
|
||||||
async created() {
|
async created() {
|
||||||
|
|
||||||
const resp = await performRequest(null, "GET", `${config.backendUrl}/dev/dump/${this.$route.params.id}`, null);
|
const resp = await performRequest(null, "GET", `${config.backendUrl}/dumps/dump/${this.$route.params.id}`, null);
|
||||||
this.dump = resp.data;
|
this.dump = resp.data;
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ export default {
|
||||||
if(query?.pageSize)
|
if(query?.pageSize)
|
||||||
params.append('limit', query.pageSize);
|
params.append('limit', query.pageSize);
|
||||||
|
|
||||||
const resp = await performRequest(null, "GET", `${config.backendUrl}/dev/dump/${params.size === 0 ? '' : '?'}${params.toString()}`, null);
|
const resp = await performRequest(null, "GET", `${config.backendUrl}/dumps/dump/${params.size === 0 ? '' : '?'}${params.toString()}`, null);
|
||||||
this.dump = resp.data;
|
this.dump = resp.data;
|
||||||
this.pagination = { page: parseInt(resp.headers.get('X-Current-Page')), pageCount: parseInt(resp.headers.get('X-Page-Count')), totalCount: parseInt(resp.headers.get('X-Total-Count'))};
|
this.pagination = { page: parseInt(resp.headers.get('X-Current-Page')), pageCount: parseInt(resp.headers.get('X-Page-Count')), totalCount: parseInt(resp.headers.get('X-Total-Count'))};
|
||||||
|
|
||||||
|
|
@ -92,4 +92,5 @@ export default {
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -30,6 +30,7 @@ import {useActiveUserStore} from "@/store/activeuser.js";
|
||||||
import Apps from "@/components/layout/config/Apps.vue";
|
import Apps from "@/components/layout/config/Apps.vue";
|
||||||
import Users from "@/components/layout/config/Users.vue";
|
import Users from "@/components/layout/config/Users.vue";
|
||||||
import CalculationDumpList from "@/components/layout/dev/CalculationDumpList.vue";
|
import CalculationDumpList from "@/components/layout/dev/CalculationDumpList.vue";
|
||||||
|
import CalculationDumps from "@/components/layout/config/CalculationDumps.vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Config",
|
name: "Config",
|
||||||
|
|
@ -59,7 +60,7 @@ export default {
|
||||||
},
|
},
|
||||||
calculationDump: {
|
calculationDump: {
|
||||||
title: 'Calculation dump',
|
title: 'Calculation dump',
|
||||||
component: markRaw(CalculationDumpList),
|
component: markRaw(CalculationDumps),
|
||||||
props: {isSelected: false},
|
props: {isSelected: false},
|
||||||
},
|
},
|
||||||
materialsTab: {
|
materialsTab: {
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ const router = createRouter({
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/config',
|
path: '/config',
|
||||||
|
name: 'config',
|
||||||
component: Config,
|
component: Config,
|
||||||
beforeEnter: async (to, from) => {
|
beforeEnter: async (to, from) => {
|
||||||
const userStore = useActiveUserStore();
|
const userStore = useActiveUserStore();
|
||||||
|
|
@ -121,7 +122,7 @@ const router = createRouter({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/dev/dump/:id',
|
path: '/dumps/dump/:id',
|
||||||
component: CalculationDump,
|
component: CalculationDump,
|
||||||
name: 'dev-calculation-dump'
|
name: 'dev-calculation-dump'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package de.avatic.lcc.controller.configuration;
|
||||||
|
|
||||||
|
import de.avatic.lcc.dto.error.CalculationJobDumpDTO;
|
||||||
|
import de.avatic.lcc.repositories.error.DumpRepository;
|
||||||
|
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
|
||||||
|
import jakarta.validation.constraints.Min;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/dumps")
|
||||||
|
public class CalculationDumpController {
|
||||||
|
|
||||||
|
private final DumpRepository dumpRepository;
|
||||||
|
|
||||||
|
public CalculationDumpController(DumpRepository dumpRepository) {
|
||||||
|
this.dumpRepository = dumpRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping({"/dump/{id}", "/dump/{id}/"})
|
||||||
|
public ResponseEntity<CalculationJobDumpDTO> getDump(@PathVariable Integer id) {
|
||||||
|
return ResponseEntity.ok(dumpRepository.getDump(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping({"/dump/", "/dump"})
|
||||||
|
public ResponseEntity<List<CalculationJobDumpDTO>> listDumps(
|
||||||
|
@RequestParam(defaultValue = "20") @Min(1) int limit,
|
||||||
|
@RequestParam(defaultValue = "1") @Min(1) int page) {
|
||||||
|
|
||||||
|
var dump = dumpRepository.listDumps(new SearchQueryPagination(page, limit));
|
||||||
|
|
||||||
|
return ResponseEntity.ok()
|
||||||
|
.header("X-Total-Count", String.valueOf(dump.getTotalElements()))
|
||||||
|
.header("X-Page-Count", String.valueOf(dump.getTotalPages()))
|
||||||
|
.header("X-Current-Page", String.valueOf(page))
|
||||||
|
.body(dump.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
package de.avatic.lcc.controller.dev;
|
package de.avatic.lcc.controller.dev;
|
||||||
|
|
||||||
import de.avatic.lcc.config.filter.DevUserEmulationFilter;
|
import de.avatic.lcc.config.filter.DevUserEmulationFilter;
|
||||||
import de.avatic.lcc.dto.error.CalculationJobDumpDTO;
|
|
||||||
import de.avatic.lcc.dto.users.UserDTO;
|
import de.avatic.lcc.dto.users.UserDTO;
|
||||||
import de.avatic.lcc.repositories.error.DumpRepository;
|
import de.avatic.lcc.repositories.error.DumpRepository;
|
||||||
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
|
import de.avatic.lcc.repositories.pagination.SearchQueryPagination;
|
||||||
|
|
@ -21,36 +20,15 @@ import java.util.List;
|
||||||
@RequestMapping({"/api/dev", "/api/dev/"})
|
@RequestMapping({"/api/dev", "/api/dev/"})
|
||||||
public class DevController {
|
public class DevController {
|
||||||
|
|
||||||
private final DumpRepository dumpRepository;
|
|
||||||
private final UserRepository userRepository;
|
private final UserRepository userRepository;
|
||||||
private final UserTransformer userTransformer;
|
private final UserTransformer userTransformer;
|
||||||
|
|
||||||
public DevController(DumpRepository dumpRepository, UserRepository userRepository, UserTransformer userTransformer) {
|
public DevController(UserRepository userRepository, UserTransformer userTransformer) {
|
||||||
|
|
||||||
this.dumpRepository = dumpRepository;
|
|
||||||
this.userRepository = userRepository;
|
this.userRepository = userRepository;
|
||||||
this.userTransformer = userTransformer;
|
this.userTransformer = userTransformer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping({"/dump/{id}", "/dump/{id}/"})
|
|
||||||
public ResponseEntity<CalculationJobDumpDTO> getDump(@PathVariable Integer id) {
|
|
||||||
return ResponseEntity.ok(dumpRepository.getDump(id));
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping({"/dump/", "/dump"})
|
|
||||||
public ResponseEntity<List<CalculationJobDumpDTO>> listDumps(
|
|
||||||
@RequestParam(defaultValue = "20") @Min(1) int limit,
|
|
||||||
@RequestParam(defaultValue = "1") @Min(1) int page) {
|
|
||||||
|
|
||||||
var dump = dumpRepository.listDumps(new SearchQueryPagination(page, limit));
|
|
||||||
|
|
||||||
return ResponseEntity.ok()
|
|
||||||
.header("X-Total-Count", String.valueOf(dump.getTotalElements()))
|
|
||||||
.header("X-Page-Count", String.valueOf(dump.getTotalPages()))
|
|
||||||
.header("X-Current-Page", String.valueOf(page))
|
|
||||||
.body(dump.toList());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping({"/user"})
|
@GetMapping({"/user"})
|
||||||
public ResponseEntity<List<UserDTO>> listUser(@RequestParam(defaultValue = "20") @Min(1) int limit,
|
public ResponseEntity<List<UserDTO>> listUser(@RequestParam(defaultValue = "20") @Min(1) int limit,
|
||||||
@RequestParam(defaultValue = "1") @Min(1) int page) {
|
@RequestParam(defaultValue = "1") @Min(1) int page) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue