mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-24 06:28:42 +01:00
feat: supports nested arrays and objects (#3979)
This commit is contained in:
@@ -1,21 +1,30 @@
|
||||
<template>
|
||||
<DefineTemplate v-slot="{ data }">
|
||||
<ul class="inline-flex flex-wrap space-x-4" @click="preventDefaultOnLinks">
|
||||
<li v-for="(value, name) in data" :key="name" v-if="isObject(data)">
|
||||
<span class="key">{{ name }}=</span>
|
||||
<span class="value" v-if="value === null"><null></span>
|
||||
<ReuseTemplate :data="value" v-if="isObject(value) || Array.isArray(value)" />
|
||||
<span v-else class="value" :class="typeof value" v-html="stripAnsi(value.toString())"></span>
|
||||
</li>
|
||||
<li v-else-if="Array.isArray(data)">
|
||||
<ul class="array inline-flex flex-wrap space-x-1">
|
||||
<li
|
||||
v-for="(item, index) in data"
|
||||
:key="index"
|
||||
class="after:text-base-content/70 not-last:after:content-[',']"
|
||||
>
|
||||
<ReuseTemplate :data="item" v-if="isObject(item) || Array.isArray(item)" />
|
||||
<span v-else class="value" :class="typeof item" v-html="stripAnsi(item.toString())"></span>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="key" v-if="Object.keys(validValues).length === 0">all values are hidden</li>
|
||||
</ul>
|
||||
</DefineTemplate>
|
||||
<LogItem :logEntry>
|
||||
<div @click="containers.length > 0 && showDrawer(LogDetails, { entry: logEntry })" class="cursor-pointer">
|
||||
<ul class="space-x-4" @click="preventDefaultOnLinks">
|
||||
<li v-for="(value, name) in validValues" :key="name" class="inline-flex">
|
||||
<span class="text-light">{{ name }}=</span>
|
||||
<span class="font-bold" v-if="value === null"><null></span>
|
||||
<span v-else-if="Array.isArray(value)" class="font-bold">
|
||||
[<span v-for="(item, index) in value" :key="index">
|
||||
<span v-html="stripAnsi(item.toString())" v-if="typeof item === 'string'"></span>
|
||||
<span v-else>{{ JSON.stringify(item) }}</span>
|
||||
<span v-if="index < value.length - 1">, </span></span
|
||||
>]
|
||||
</span>
|
||||
<span class="font-bold" v-html="stripAnsi(value.toString())" v-else></span>
|
||||
</li>
|
||||
<li class="text-light" v-if="Object.keys(validValues).length === 0">all values are hidden</li>
|
||||
</ul>
|
||||
<ReuseTemplate :data="validValues" />
|
||||
</div>
|
||||
</LogItem>
|
||||
</template>
|
||||
@@ -31,6 +40,8 @@ const { logEntry } = defineProps<{
|
||||
|
||||
const { containers } = useLoggingContext();
|
||||
|
||||
const [DefineTemplate, ReuseTemplate] = createReusableTemplate();
|
||||
|
||||
const validValues = computed(() => {
|
||||
return Object.fromEntries(Object.entries(logEntry.message).filter(([_, value]) => value !== undefined));
|
||||
});
|
||||
@@ -45,7 +56,19 @@ function preventDefaultOnLinks(event: MouseEvent) {
|
||||
|
||||
<style scoped>
|
||||
@reference "@/main.css";
|
||||
.text-light {
|
||||
@apply text-base-content/70;
|
||||
.key {
|
||||
@apply text-base-content/70 font-light;
|
||||
}
|
||||
|
||||
.value {
|
||||
@apply text-base-content font-bold;
|
||||
}
|
||||
|
||||
.array {
|
||||
@apply before:text-base-content/80 after:text-base-content/80 before:content-['['] after:content-[']'];
|
||||
}
|
||||
|
||||
.string {
|
||||
@apply before:content-['"'] after:content-['"'];
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import stripAnsi from "strip-ansi";
|
||||
import { Container } from "@/models/Container";
|
||||
import { LogEntry, SimpleLogEntry, ComplexLogEntry, JSONObject } from "@/models/LogEntry";
|
||||
import LogDetails from "./LogDetails.vue";
|
||||
@@ -80,9 +81,9 @@ const { t } = useI18n();
|
||||
|
||||
async function copyLogMessage() {
|
||||
if (logEntry instanceof ComplexLogEntry) {
|
||||
await copy(logEntry.rawMessage);
|
||||
await copy(stripAnsi(logEntry.rawMessage));
|
||||
} else if (logEntry instanceof SimpleLogEntry) {
|
||||
await copy(logEntry.message);
|
||||
await copy(stripAnsi(logEntry.rawMessage));
|
||||
}
|
||||
|
||||
if (copied.value) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<header class="flex items-center gap-4">
|
||||
<Tag :data-level="entry.level" class="text-white uppercase" v-if="entry.level">{{ entry.level }}</Tag>
|
||||
<Tag :data-level="entry.level" class="show-unknown text-white uppercase" v-if="entry.level">{{ entry.level }}</Tag>
|
||||
<h1 class="text-lg max-md:hidden">
|
||||
<DateTime :date="entry.date" />
|
||||
</h1>
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
<template>
|
||||
<div :data-level="level" :data-position="position" class="mt-1.5 size-2.5 flex-none rounded-lg"></div>
|
||||
<div
|
||||
:data-level="level"
|
||||
:data-position="position"
|
||||
class="mt-1.5 size-2.5 flex-none rounded-lg"
|
||||
:class="{ showUnknown }"
|
||||
></div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
import { Position } from "@/models/LogEntry";
|
||||
import { Position, Level } from "@/models/LogEntry";
|
||||
|
||||
defineProps<{
|
||||
level?: string;
|
||||
const {
|
||||
level,
|
||||
position,
|
||||
showUnknown = false,
|
||||
} = defineProps<{
|
||||
level?: Level;
|
||||
position?: Position;
|
||||
showUnknown?: boolean;
|
||||
}>();
|
||||
</script>
|
||||
|
||||
@@ -53,4 +63,8 @@ defineProps<{
|
||||
[data-level="warn"] {
|
||||
@apply !bg-orange;
|
||||
}
|
||||
|
||||
[data-level="unknown"].show-unknown {
|
||||
@apply !bg-base-300;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user