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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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