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:
@@ -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>
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -16,7 +16,7 @@ label:
|
||||
username: Имя пользователя
|
||||
container-name: Имя контейнера
|
||||
status: Статус
|
||||
last-started: Последний запуск
|
||||
created: Создан
|
||||
avg-cpu: средний процессор (%)
|
||||
avg-mem: средняя память (%)
|
||||
tooltip:
|
||||
|
||||
@@ -16,7 +16,7 @@ label:
|
||||
username: 用户名
|
||||
container-name: 容器名称
|
||||
status: 状态
|
||||
last-started: 最后启动
|
||||
created: 创建时间
|
||||
avg-cpu: 平均CPU (%)
|
||||
avg-mem: 平均MEM (%)
|
||||
tooltip:
|
||||
|
||||
Reference in New Issue
Block a user