Files
cloudron-box/dashboard/src/components/app/Eventlog.vue
T
2025-12-10 18:04:07 +01:00

145 lines
3.8 KiB
Vue

<script setup>
import { prettyLongDate } from '@cloudron/pankow/utils';
import { ref, onMounted } from 'vue';
import { eventlogSource, eventlogDetails } from '../../utils.js';
import AppsModel from '../../models/AppsModel.js';
const appsModel = AppsModel.create();
const props = defineProps([ 'app' ]);
const busy = ref(true);
const eventlogs = ref([]);
onMounted(async () => {
const [error, result] = await appsModel.getEvents(props.app.id);
if (error) return console.error(error);
eventlogs.value = result.map(e => {
return {
id: Symbol(),
raw: e,
details: eventlogDetails(e, props.app),
source: eventlogSource(e, props.app),
};
});
busy.value = false;
});
</script>
<template>
<div>
<div class="eventlog-list pankow-no-desktop">
<div class="eventlog-list-item" v-for="eventlog in eventlogs" :key="eventlog.id" :class="{ 'active': eventlog.isOpen }">
<div @click="eventlog.isOpen = !eventlog.isOpen" style="display: flex; justify-content: space-between; padding: 0 10px" >
<div style="white-space: nowrap;">
{{ prettyLongDate(eventlog.raw.creationTime) }}
<b style="margin-left: 10px">{{ eventlog.raw.action }}</b>
</div>
<div>{{ eventlog.source }}</div>
</div>
<div v-show="eventlog.isOpen">
<div class="eventlog-details" style="margin-top: 10px; padding-top: 5px">
<div v-if="eventlog.raw.source.ip" class="eventlog-source">Source IP: <span @click="onCopySource(eventlog)">{{ eventlog.raw.source.ip }}</span></div>
<pre>{{ JSON.stringify(eventlog.raw.data, null, 4) }}</pre>
</div>
</div>
</div>
</div>
<table class="eventlog-table pankow-no-mobile">
<thead>
<tr>
<th style="width: 160px">{{ $t('eventlog.time') }}</th>
<th style="width: 15%">{{ $t('eventlog.source') }}</th>
<th style="word-break: break-all; overflow-wrap: anywhere;">{{ $t('eventlog.details') }}</th>
</tr>
</thead>
<tbody>
<template v-for="eventlog in eventlogs" :key="eventlog.id">
<tr @click="eventlog.isOpen = !eventlog.isOpen" :class="{ 'active': eventlog.isOpen }" >
<td style="white-space: nowrap;">{{ prettyLongDate(eventlog.raw.creationTime) }}</td>
<td>{{ eventlog.source }}</td>
<td v-html="eventlog.details"></td>
</tr>
<tr v-show="eventlog.isOpen">
<td colspan="3" class="eventlog-details">
<div v-if="eventlog.raw.source.ip" class="eventlog-source">Source IP: <span @click="onCopySource(eventlog)">{{ eventlog.raw.source.ip }}</span></div>
<pre>{{ JSON.stringify(eventlog.raw.data, null, 4) }}</pre>
</td>
</tr>
</template>
</tbody>
</table>
</div>
</template>
<style scoped>
.eventlog-table {
width: 100%;
overflow: auto;
border-spacing: 0px;
}
.eventlog-table th {
text-align: left;
}
.eventlog-table tbody tr {
cursor: pointer;
}
.eventlog-table tbody tr.active,
.eventlog-table tbody tr:hover {
background-color: var(--pankow-color-background-hover);
}
.eventlog-table th,
.eventlog-table td {
padding: 10px 6px;
}
.eventlog-filter {
display: flex;
gap: 5px;
flex-wrap: wrap;
margin: 20px 0;
}
.eventlog-details {
background-color: color-mix(in oklab, var(--pankow-color-background-hover), black 5%);
cursor: auto;
position: relative;
}
.eventlog-source {
padding-left: 10px;
padding-bottom: 10px;
cursor: copy;
}
.eventlog-details pre {
white-space: pre-wrap;
color: var(--pankow-text-color);
font-size: 13px;
padding-left: 10px;
margin: 0;
border: none;
border-radius: var(--pankow-border-radius);
}
.eventlog-list-item.active {
background-color: var(--pankow-color-background-hover);
}
.eventlog-list-item {
padding: 10px 0;
cursor: pointer;
}
</style>