redo of frontend style part 1
This commit is contained in:
parent
4faf14c518
commit
2e2437660b
5 changed files with 312 additions and 100 deletions
|
@ -29,5 +29,6 @@
|
|||
"vite": "^5.1.5",
|
||||
"vite-plugin-vuetify": "^2.0.3",
|
||||
"vue-tsc": "^2.0.6"
|
||||
}
|
||||
},
|
||||
"packageManager": "pnpm@9.12.1+sha512.e5a7e52a4183a02d5931057f7a0dbff9d5e9ce3161e33fa68ae392125b79282a8a8a470a51dfc8a0ed86221442eb2fb57019b0990ed24fab519bf0e1bc5ccfc4"
|
||||
}
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
<template>
|
||||
<v-app>
|
||||
<v-main>
|
||||
<!-- <div v-if="store.token === null">
|
||||
<!--
|
||||
<div v-if="store.token === null">
|
||||
<loginPage />
|
||||
</div>
|
||||
<div v-else> -->
|
||||
<div v-else>
|
||||
<MainPage />
|
||||
<!--</div>-->
|
||||
</div>
|
||||
-->
|
||||
<MainPage />
|
||||
</v-main>
|
||||
</v-app>
|
||||
</template>
|
||||
|
@ -21,6 +24,6 @@ import { store } from "./store";
|
|||
html,
|
||||
body,
|
||||
main {
|
||||
background-color: #e3e3e3;
|
||||
background-color: #2B3037;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,95 +1,67 @@
|
|||
<template>
|
||||
<div>
|
||||
<HeaderBar />
|
||||
<div class="ma-8">
|
||||
<div v-if="isPending">Loading...</div>
|
||||
<ul v-else-if="data">
|
||||
<li v-for="nodeGroup in data" :key="nodeGroup.groupId">
|
||||
<CategoryContainer :nodeGroup="nodeGroup" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import HeaderBar from "./HeaderBar.vue";
|
||||
import CategoryContainer from "./CategoryContainer.vue";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { axiosInstance } from "@/client";
|
||||
import { NodeGroup } from "@/types";
|
||||
import { search, key } from "@/store";
|
||||
import MiniSearch from "minisearch";
|
||||
import { computed, provide } from "vue";
|
||||
|
||||
const mockNodeGroups: NodeGroup[] = [
|
||||
{
|
||||
groupId: "group-1",
|
||||
name: "Test Node Group 1",
|
||||
nodes: [
|
||||
{
|
||||
uuid: "123e4567-e89b-12d3-a456-426614174000",
|
||||
name: "Sensor Node A1",
|
||||
status: 502,
|
||||
coordla: 52.5200,
|
||||
coordlong: 13.4050,
|
||||
temperature: 22.5,
|
||||
battery: 85,
|
||||
runtime: 120,
|
||||
},
|
||||
{
|
||||
uuid: "223e4567-e89b-12d3-a456-426614174001",
|
||||
name: "Sensor Node A2",
|
||||
status: 200,
|
||||
coordla: 48.8566,
|
||||
coordlong: 2.3522,
|
||||
temperature: 20.0,
|
||||
battery: 90,
|
||||
runtime: 100,
|
||||
},
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
const { isPending, isError, data, error } = useQuery({
|
||||
queryKey: ["nodeGroups"],
|
||||
queryFn: async () => {
|
||||
//hier der API-Call für die Daten
|
||||
return mockNodeGroups;
|
||||
},
|
||||
refetchInterval: 1 * 1,
|
||||
});
|
||||
|
||||
const searchEngine = computed(() => {
|
||||
const minisearch = new MiniSearch({
|
||||
fields: ["name", "groupId"],
|
||||
searchOptions: {
|
||||
boost: { name: 2 },
|
||||
prefix: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (data.value) {
|
||||
minisearch.addAll(data.value);
|
||||
}
|
||||
return minisearch;
|
||||
});
|
||||
|
||||
const searching = computed(() => search.value !== "");
|
||||
|
||||
const visibleIds = computed(() => {
|
||||
return searching.value ? searchEngine.value.search(search.value).map(result => result.groupId) : [];
|
||||
});
|
||||
|
||||
provide(key, {
|
||||
visibleIds,
|
||||
searching,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
li,
|
||||
ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
</style>
|
||||
<template>
|
||||
<div>
|
||||
<HeaderBar />
|
||||
<div style="margin: 15px">
|
||||
<TableCategory></TableCategory>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import HeaderBar from "./HeaderBar.vue";
|
||||
import CategoryContainer from "./CategoryContainer.vue";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { axiosInstance } from "@/client";
|
||||
import { LicenseGroup, License } from "@/types";
|
||||
import { search, key } from "@/store";
|
||||
import MiniSearch from "minisearch";
|
||||
import { computed, provide } from "vue";
|
||||
import TableCategory from "./TableCategory.vue";
|
||||
|
||||
const { isPending, isError, data, error } = useQuery({
|
||||
queryKey: ["licenses"],
|
||||
queryFn: async () => {
|
||||
const res = await axiosInstance.get<LicenseGroup[]>("/licenses");
|
||||
console.log(res.data);
|
||||
return res.data;
|
||||
},
|
||||
refetchInterval: 60 * 1000,
|
||||
});
|
||||
|
||||
const searchEngine = computed(() => {
|
||||
let minisearch = new MiniSearch({
|
||||
fields: ["name", "description", "id"],
|
||||
searchOptions: {
|
||||
boost: { name: 2 },
|
||||
prefix: true,
|
||||
},
|
||||
});
|
||||
let licenses: License[] = [];
|
||||
data.value?.forEach((group) => {
|
||||
group.licenses.forEach((license) => licenses.push(license));
|
||||
});
|
||||
console.log(licenses);
|
||||
minisearch.addAll(licenses);
|
||||
return minisearch;
|
||||
});
|
||||
|
||||
const searching = computed(() => search.value !== "");
|
||||
|
||||
const visibleIds = computed(() => {
|
||||
return searchEngine.value.search(search.value).map((searchResult) => {
|
||||
return searchResult.id;
|
||||
});
|
||||
});
|
||||
|
||||
provide(key, {
|
||||
visibleIds,
|
||||
searching,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
li,
|
||||
ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
</style>
|
||||
|
|
141
web/src/components/TableCategory.vue
Normal file
141
web/src/components/TableCategory.vue
Normal file
|
@ -0,0 +1,141 @@
|
|||
<template>
|
||||
<div class="table-container">
|
||||
<table class="responsive-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Node/Name</th>
|
||||
<th>Status</th>
|
||||
<th>Latitude</th> <!-- Separate column for Latitude -->
|
||||
<th>Longitude</th> <!-- Separate column for Longitude -->
|
||||
<th>Battery</th>
|
||||
<th>Gemessene - Temperatur</th>
|
||||
<th>Laufzeit</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="(node, index) in tableData" :key="index">
|
||||
<td>{{ node.name }}</td>
|
||||
<td>
|
||||
<span :class="node.status === 'ONLINE' ? 'status-online' : 'status-offline'">
|
||||
{{ node.status }}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{ node.position.lat }}</td>
|
||||
<td>{{ node.position.lng }}</td>
|
||||
<td>{{ node.battery }}%</td>
|
||||
<td>{{ node.temperature }}°C</td>
|
||||
<td>{{ node.runtime }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
tableData: [
|
||||
{
|
||||
name: "XXXX-XXXX-XXXX-XXXX",
|
||||
status: "ONLINE",
|
||||
position: { lat: 40.7128, lng: 74.0012 },
|
||||
battery: 98,
|
||||
temperature: 100,
|
||||
runtime: "12h 30m 12s",
|
||||
},
|
||||
{
|
||||
name: "XXXX-XXXX-XXXX-XXXX",
|
||||
status: "OFFLINE",
|
||||
position: { lat: 40.7128, lng: 74.0012 },
|
||||
battery: 19,
|
||||
temperature: 100,
|
||||
runtime: "30m",
|
||||
},
|
||||
{
|
||||
name: "Localnode-3",
|
||||
status: "ONLINE",
|
||||
position: { lat: 40.7128, lng: 74.0012 },
|
||||
battery: 66,
|
||||
temperature: 100,
|
||||
runtime: "12h 30m 12s",
|
||||
},
|
||||
{
|
||||
name: "XXXX-XXXX-XXXX-XXXX",
|
||||
status: "ONLINE",
|
||||
position: { lat: 40.7128, lng: 74.0012 },
|
||||
battery: 79,
|
||||
temperature: 100,
|
||||
runtime: "12h 30m 12s",
|
||||
},
|
||||
{
|
||||
name: "XXXX-XXXX-XXXX-XXXX",
|
||||
status: "ONLINE",
|
||||
position: { lat: 40.7128, lng: 74.0012 },
|
||||
battery: 10,
|
||||
temperature: 100,
|
||||
runtime: "12h 30m 12s",
|
||||
},
|
||||
{
|
||||
name: "XXXX-XXXX-XXXX-XXXX",
|
||||
status: "OFFLINE",
|
||||
position: { lat: 40.7128, lng: 74.0012 },
|
||||
battery: 0,
|
||||
temperature: 100,
|
||||
runtime: "12h 30m 12s",
|
||||
},
|
||||
{
|
||||
name: "XXXX-XXXX-XXXX-XXXX",
|
||||
status: "ONLINE",
|
||||
position: { lat: 40.7128, lng: 74.0012 },
|
||||
battery: 56,
|
||||
temperature: 100,
|
||||
runtime: "12h 30m 12s",
|
||||
},
|
||||
],
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.table-container {
|
||||
background-color: white;
|
||||
padding: 0.5rem 1rem; /* Reduce top padding to 0.5rem */
|
||||
margin: 0 auto; /* Remove margin at the top, keep it centered horizontally */
|
||||
width: 100%; /* Full width of parent */
|
||||
overflow-x: auto; /* Allow horizontal scroll if necessary */
|
||||
}
|
||||
|
||||
.responsive-table {
|
||||
width: 100%; /* Full width */
|
||||
border-collapse: collapse; /* Ensure tight borders */
|
||||
margin: 0; /* Remove margin at the top of the table */
|
||||
table-layout: auto; /* Auto layout for slimmer columns */
|
||||
}
|
||||
|
||||
.responsive-table th,
|
||||
.responsive-table td {
|
||||
padding: 0.5rem; /* Maintain slim padding */
|
||||
text-align: center; /* Center text */
|
||||
border-bottom: 1px solid #ddd;
|
||||
}
|
||||
|
||||
.responsive-table th {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.responsive-table tr:nth-child(even) {
|
||||
background-color: #f9f9f9; /* Striped rows */
|
||||
}
|
||||
|
||||
.status-online {
|
||||
color: green;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.status-offline {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
95
web/src/components/oldMain.vue
Normal file
95
web/src/components/oldMain.vue
Normal file
|
@ -0,0 +1,95 @@
|
|||
<template>
|
||||
<div>
|
||||
<HeaderBar />
|
||||
<div class="ma-8">
|
||||
<div v-if="isPending">Loading...</div>
|
||||
<ul v-else-if="data">
|
||||
<li v-for="nodeGroup in data" :key="nodeGroup.groupId">
|
||||
<CategoryContainer :nodeGroup="nodeGroup" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import HeaderBar from "./HeaderBar.vue";
|
||||
import CategoryContainer from "./CategoryContainer.vue";
|
||||
import { useQuery } from "@tanstack/vue-query";
|
||||
import { axiosInstance } from "@/client";
|
||||
import { NodeGroup } from "@/types";
|
||||
import { search, key } from "@/store";
|
||||
import MiniSearch from "minisearch";
|
||||
import { computed, provide } from "vue";
|
||||
|
||||
const mockNodeGroups: NodeGroup[] = [
|
||||
{
|
||||
groupId: "group-1",
|
||||
name: "Test Node Group 1",
|
||||
nodes: [
|
||||
{
|
||||
uuid: "123e4567-e89b-12d3-a456-426614174000",
|
||||
name: "Sensor Node A1",
|
||||
status: 502,
|
||||
coordla: 52.5200,
|
||||
coordlong: 13.4050,
|
||||
temperature: 22.5,
|
||||
battery: 85,
|
||||
runtime: 120,
|
||||
},
|
||||
{
|
||||
uuid: "223e4567-e89b-12d3-a456-426614174001",
|
||||
name: "Sensor Node A2",
|
||||
status: 200,
|
||||
coordla: 48.8566,
|
||||
coordlong: 2.3522,
|
||||
temperature: 20.0,
|
||||
battery: 90,
|
||||
runtime: 100,
|
||||
},
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
const { isPending, isError, data, error } = useQuery({
|
||||
queryKey: ["nodeGroups"],
|
||||
queryFn: async () => {
|
||||
//hier der API-Call für die Daten
|
||||
return mockNodeGroups;
|
||||
},
|
||||
refetchInterval: 1 * 1,
|
||||
});
|
||||
|
||||
const searchEngine = computed(() => {
|
||||
const minisearch = new MiniSearch({
|
||||
fields: ["name", "groupId"],
|
||||
searchOptions: {
|
||||
boost: { name: 2 },
|
||||
prefix: true,
|
||||
},
|
||||
});
|
||||
|
||||
if (data.value) {
|
||||
minisearch.addAll(data.value);
|
||||
}
|
||||
return minisearch;
|
||||
});
|
||||
|
||||
const searching = computed(() => search.value !== "");
|
||||
|
||||
const visibleIds = computed(() => {
|
||||
return searching.value ? searchEngine.value.search(search.value).map(result => result.groupId) : [];
|
||||
});
|
||||
|
||||
provide(key, {
|
||||
visibleIds,
|
||||
searching,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
li,
|
||||
ul {
|
||||
list-style-type: none;
|
||||
}
|
||||
</style>
|
Loading…
Add table
Reference in a new issue