1
0
mirror of https://github.com/amir20/dozzle.git synced 2025-12-21 13:23:07 +01:00

feat: updates home dashboard to support mobile view (#2334)

* feat: updates home dashboard to support mobile view

* updates created translation

* adds ellipses
This commit is contained in:
Amir Raminfar
2023-08-01 12:35:05 -07:00
committed by GitHub
parent 5d326189a8
commit 3eb222066c
7 changed files with 70 additions and 43 deletions

View File

@@ -4,14 +4,15 @@
<thead> <thead>
<tr :data-direction="direction > 0 ? 'asc' : 'desc'"> <tr :data-direction="direction > 0 ? 'asc' : 'desc'">
<th <th
v-for="(label, field) in headers" v-for="(value, key) in fields"
:key="field" :key="key"
@click.prevent="sort(field)" @click.prevent="sort(key)"
:class="{ 'selected-sort': field === sortField }" :class="{ 'selected-sort': key === sortField }"
v-show="isVisible(key)"
> >
<a> <a>
<span class="icon-text"> <span class="icon-text">
<span>{{ $t(label) }}</span> <span>{{ $t(value.label) }}</span>
<span class="icon"> <span class="icon">
<mdi:arrow-up /> <mdi:arrow-up />
</span> </span>
@@ -22,17 +23,19 @@
</thead> </thead>
<tbody> <tbody>
<tr v-for="container in paginated" :key="container.id"> <tr v-for="container in paginated" :key="container.id">
<td> <td v-if="isVisible('name')">
<router-link :to="{ name: 'container-id', params: { id: container.id } }" :title="container.name"> <router-link :to="{ name: 'container-id', params: { id: container.id } }" :title="container.name">
{{ container.name }} {{ container.name }}
</router-link> </router-link>
</td> </td>
<td>{{ container.state }}</td> <td v-if="isVisible('state')">{{ container.state }}</td>
<td><distance-time :date="container.created" strict :suffix="false"></distance-time></td> <td v-if="isVisible('created')">
<td> <distance-time :date="container.created" strict :suffix="false"></distance-time>
</td>
<td v-if="isVisible('cpu')">
{{ (container.movingAverage.cpu / 100).toLocaleString(undefined, { style: "percent" }) }} {{ (container.movingAverage.cpu / 100).toLocaleString(undefined, { style: "percent" }) }}
</td> </td>
<td> <td v-if="isVisible('mem')">
{{ (container.movingAverage.memory / 100).toLocaleString(undefined, { style: "percent" }) }} {{ (container.movingAverage.memory / 100).toLocaleString(undefined, { style: "percent" }) }}
</td> </td>
</tr> </tr>
@@ -50,41 +53,55 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
const headers = { const fields = {
name: "label.container-name", name: {
state: "label.status", label: "label.container-name",
created: "label.last-started", sortFunc: (a: Container, b: Container) => a.name.localeCompare(b.name) * direction.value,
cpu: "label.avg-cpu", mobileVisible: true,
mem: "label.avg-mem", },
state: {
label: "label.status",
sortFunc: (a: Container, b: Container) => a.state.localeCompare(b.state) * direction.value,
mobileVisible: false,
},
created: {
label: "label.created",
sortFunc: (a: Container, b: Container) => (a.created.getTime() - b.created.getTime()) * direction.value,
mobileVisible: true,
},
cpu: {
label: "label.avg-cpu",
sortFunc: (a: Container, b: Container) => (a.movingAverage.cpu - b.movingAverage.cpu) * direction.value,
mobileVisible: false,
},
mem: {
label: "label.avg-mem",
sortFunc: (a: Container, b: Container) => (a.movingAverage.memory - b.movingAverage.memory) * direction.value,
mobileVisible: false,
},
}; };
type Container = {
id: string;
name: string;
state: string;
created: Date;
movingAverage: {
cpu: number;
memory: number;
};
};
const { containers, perPage = 15 } = defineProps<{ const { containers, perPage = 15 } = defineProps<{
containers: { containers: Container[];
movingAverage: { cpu: number; memory: number };
created: Date;
state: string;
name: string;
id: string;
}[];
perPage?: number; perPage?: number;
}>(); }>();
const sortField: Ref<keyof typeof headers> = ref("created"); const sortField: Ref<keyof typeof fields> = ref("created");
const direction = ref<1 | -1>(-1); const direction = ref<1 | -1>(-1);
const sortedContainers = computedWithControl( const sortedContainers = computedWithControl(
() => [containers.length, sortField.value, direction.value], () => [containers.length, sortField.value, direction.value],
() => { () => {
return containers.sort((a, b) => { return containers.sort((a, b) => {
switch (sortField.value) { return fields[sortField.value].sortFunc(a, b);
case "name":
return a.name.localeCompare(b.name) * direction.value;
case "state":
return a.state.localeCompare(b.state) * direction.value;
case "created":
return (a.created.getTime() - b.created.getTime()) * direction.value;
case "cpu":
return (a.movingAverage.cpu - b.movingAverage.cpu) * direction.value;
case "mem":
return (a.movingAverage.memory - b.movingAverage.memory) * direction.value;
}
}); });
}, },
); );
@@ -99,7 +116,7 @@ const paginated = computed(() => {
return sortedContainers.value.slice(start, end); return sortedContainers.value.slice(start, end);
}); });
function sort(field: keyof typeof headers) { function sort(field: keyof typeof fields) {
if (sortField.value === field) { if (sortField.value === field) {
direction.value *= -1; direction.value *= -1;
} else { } else {
@@ -107,6 +124,9 @@ function sort(field: keyof typeof headers) {
direction.value = 1; direction.value = 1;
} }
} }
function isVisible(field: keyof typeof fields) {
return fields[field].mobileVisible || !isMobile.value;
}
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -124,4 +144,11 @@ function sort(field: keyof typeof headers) {
display: inline-block; display: inline-block;
} }
} }
tbody td {
max-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
</style> </style>

View File

@@ -16,7 +16,7 @@ label:
username: Benutzername username: Benutzername
container-name: Container Name container-name: Container Name
status: Status status: Status
last-started: Zuletzt gestartet created: Erstellt
avg-cpu: Avg CPU (%) avg-cpu: Avg CPU (%)
avg-mem: Avg MEM (%) avg-mem: Avg MEM (%)
tooltip: tooltip:

View File

@@ -16,7 +16,7 @@ label:
username: Username username: Username
container-name: Container Name container-name: Container Name
status: Status status: Status
last-started: Last started created: Created
avg-cpu: Avg. CPU (%) avg-cpu: Avg. CPU (%)
avg-mem: Avg. MEM (%) avg-mem: Avg. MEM (%)
tooltip: tooltip:

View File

@@ -16,7 +16,7 @@ label:
username: Nombre de usuario username: Nombre de usuario
container-name: Nombre del contenedor container-name: Nombre del contenedor
status: Estado status: Estado
last-started: Último inicio created: Creado
avg-cpu: Promedio de CPU (%) avg-cpu: Promedio de CPU (%)
avg-mem: Promedio de MEM (%) avg-mem: Promedio de MEM (%)
tooltip: tooltip:

View File

@@ -16,7 +16,7 @@ label:
username: Nome de usuário username: Nome de usuário
container-name: Nome do contentor container-name: Nome do contentor
status: Estado status: Estado
last-started: Última iniciada created: Criado
avg-cpu: Média de CPU (%) avg-cpu: Média de CPU (%)
avg-mem: Média de MEM (%) avg-mem: Média de MEM (%)
tooltip: tooltip:

View File

@@ -16,7 +16,7 @@ label:
username: Имя пользователя username: Имя пользователя
container-name: Имя контейнера container-name: Имя контейнера
status: Статус status: Статус
last-started: Последний запуск created: Создан
avg-cpu: средний процессор (%) avg-cpu: средний процессор (%)
avg-mem: средняя память (%) avg-mem: средняя память (%)
tooltip: tooltip:

View File

@@ -16,7 +16,7 @@ label:
username: 用户名 username: 用户名
container-name: 容器名称 container-name: 容器名称
status: 状态 status: 状态
last-started: 最后启动 created: 创建时间
avg-cpu: 平均CPU (%) avg-cpu: 平均CPU (%)
avg-mem: 平均MEM (%) avg-mem: 平均MEM (%)
tooltip: tooltip: