mirror of
https://github.com/amir20/dozzle.git
synced 2025-12-21 21:33:18 +01:00
chore: refactors code by moving loader to a log entry (#3951)
This commit is contained in:
1
assets/components.d.ts
vendored
1
assets/components.d.ts
vendored
@@ -53,6 +53,7 @@ declare module 'vue' {
|
|||||||
KeyShortcut: typeof import('./components/common/KeyShortcut.vue')['default']
|
KeyShortcut: typeof import('./components/common/KeyShortcut.vue')['default']
|
||||||
LabeledInput: typeof import('./components/common/LabeledInput.vue')['default']
|
LabeledInput: typeof import('./components/common/LabeledInput.vue')['default']
|
||||||
Links: typeof import('./components/Links.vue')['default']
|
Links: typeof import('./components/Links.vue')['default']
|
||||||
|
LoadMoreLogItem: typeof import('./components/LogViewer/LoadMoreLogItem.vue')['default']
|
||||||
LogAnalytics: typeof import('./components/LogViewer/LogAnalytics.vue')['default']
|
LogAnalytics: typeof import('./components/LogViewer/LogAnalytics.vue')['default']
|
||||||
LogDate: typeof import('./components/LogViewer/LogDate.vue')['default']
|
LogDate: typeof import('./components/LogViewer/LogDate.vue')['default']
|
||||||
LogDetails: typeof import('./components/LogViewer/LogDetails.vue')['default']
|
LogDetails: typeof import('./components/LogViewer/LogDetails.vue')['default']
|
||||||
|
|||||||
@@ -1,31 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div ref="root" class="flex min-h-[1px] justify-center">
|
|
||||||
<span class="loading loading-bars loading-md text-primary mt-4" v-show="isLoading"></span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script lang="ts" setup>
|
|
||||||
const { onLoadMore = () => Promise.resolve(), enabled } = defineProps<{
|
|
||||||
onLoadMore: () => Promise<void>;
|
|
||||||
enabled: boolean;
|
|
||||||
}>();
|
|
||||||
|
|
||||||
const isLoading = ref(false);
|
|
||||||
const root = ref<HTMLElement>();
|
|
||||||
|
|
||||||
const observer = new IntersectionObserver(async (entries) => {
|
|
||||||
if (entries[0].intersectionRatio <= 0) return;
|
|
||||||
if (onLoadMore && enabled) {
|
|
||||||
const scrollingParent = root.value?.closest("[data-scrolling]") || document.documentElement;
|
|
||||||
const previousHeight = scrollingParent.scrollHeight;
|
|
||||||
isLoading.value = true;
|
|
||||||
await onLoadMore();
|
|
||||||
isLoading.value = false;
|
|
||||||
await nextTick();
|
|
||||||
scrollingParent.scrollTop += scrollingParent.scrollHeight - previousHeight;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
onMounted(() => observer.observe(root.value!));
|
|
||||||
onUnmounted(() => observer.disconnect());
|
|
||||||
</script>
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
<template>
|
<template>
|
||||||
<InfiniteLoader :onLoadMore="fetchMore" :enabled="!loadingMore && messages.length > 10" />
|
|
||||||
<ul class="flex animate-pulse flex-col gap-4 p-4" v-if="loading || (noLogs && waitingForMoreLog)">
|
<ul class="flex animate-pulse flex-col gap-4 p-4" v-if="loading || (noLogs && waitingForMoreLog)">
|
||||||
<div class="flex flex-row gap-2" v-for="size in sizes">
|
<div class="flex flex-row gap-2" v-for="size in sizes">
|
||||||
<div class="bg-base-content/50 h-3 w-40 shrink-0 rounded-full opacity-50"></div>
|
<div class="bg-base-content/50 h-3 w-40 shrink-0 rounded-full opacity-50"></div>
|
||||||
@@ -22,10 +21,8 @@ const { entity, streamSource } = $defineProps<{
|
|||||||
entity: T;
|
entity: T;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const { messages, loadOlderLogs, isLoadingMore, opened, loading, error, eventSourceURL } = streamSource(
|
const { messages, opened, loading, error, eventSourceURL } = streamSource(toRef(() => entity));
|
||||||
toRef(() => entity),
|
|
||||||
);
|
|
||||||
const { loadingMore } = useLoggingContext();
|
|
||||||
const color = computed(() => {
|
const color = computed(() => {
|
||||||
if (error.value) return "error";
|
if (error.value) return "error";
|
||||||
if (loading.value) return "secondary";
|
if (loading.value) return "secondary";
|
||||||
@@ -41,14 +38,6 @@ defineExpose({
|
|||||||
clear: () => (messages.value = []),
|
clear: () => (messages.value = []),
|
||||||
});
|
});
|
||||||
|
|
||||||
const fetchMore = async () => {
|
|
||||||
if (!isLoadingMore.value) {
|
|
||||||
loadingMore.value = true;
|
|
||||||
await loadOlderLogs();
|
|
||||||
loadingMore.value = false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const sizes = computedWithControl(eventSourceURL, () => {
|
const sizes = computedWithControl(eventSourceURL, () => {
|
||||||
const sizeOptions = [
|
const sizeOptions = [
|
||||||
"w-2/12",
|
"w-2/12",
|
||||||
|
|||||||
29
assets/components/LogViewer/LoadMoreLogItem.vue
Normal file
29
assets/components/LogViewer/LoadMoreLogItem.vue
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<template>
|
||||||
|
<div ref="root" class="flex min-h-[1px] flex-1 content-center justify-center p-2">
|
||||||
|
<span class="loading loading-bars loading-md text-primary" v-show="isLoading"></span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { LoadMoreLogEntry } from "@/models/LogEntry";
|
||||||
|
|
||||||
|
const { logEntry } = defineProps<{
|
||||||
|
logEntry: LoadMoreLogEntry;
|
||||||
|
}>();
|
||||||
|
|
||||||
|
const isLoading = ref(false);
|
||||||
|
const root = ref<HTMLElement>();
|
||||||
|
|
||||||
|
useIntersectionObserver(root, async (entries) => {
|
||||||
|
if (entries[0].intersectionRatio <= 0) return;
|
||||||
|
if (isLoading.value) return;
|
||||||
|
const scrollingParent = root.value?.closest("[data-scrolling]") || document.documentElement;
|
||||||
|
const previousHeight = scrollingParent.scrollHeight;
|
||||||
|
isLoading.value = true;
|
||||||
|
await logEntry.loadMore();
|
||||||
|
isLoading.value = false;
|
||||||
|
await nextTick();
|
||||||
|
scrollingParent.scrollTop += scrollingParent.scrollHeight - previousHeight;
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped></style>
|
||||||
@@ -16,16 +16,12 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { type JSONObject, LogEntry } from "@/models/LogEntry";
|
import { type JSONObject, LogEntry } from "@/models/LogEntry";
|
||||||
|
|
||||||
const { loading, progress, currentDate } = useScrollContext();
|
const { progress, currentDate } = useScrollContext();
|
||||||
|
|
||||||
const { messages } = defineProps<{
|
const { messages } = defineProps<{
|
||||||
messages: LogEntry<string | JSONObject>[];
|
messages: LogEntry<string | JSONObject>[];
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
watchEffect(() => {
|
|
||||||
loading.value = messages.length === 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
const { containers } = useLoggingContext();
|
const { containers } = useLoggingContext();
|
||||||
|
|
||||||
const list = ref<HTMLElement[]>([]);
|
const list = ref<HTMLElement[]>([]);
|
||||||
|
|||||||
@@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
exports[`<ContainerEventSource /> > render html correctly > should render dates with 12 hour style 1`] = `
|
exports[`<ContainerEventSource /> > render html correctly > should render dates with 12 hour style 1`] = `
|
||||||
"<ul data-v-cf9ff940="" class="group pt-4 medium" data-logs="" show-container-name="false">
|
"<ul data-v-cf9ff940="" class="group pt-4 medium" data-logs="" show-container-name="false">
|
||||||
|
<li data-v-cf9ff940="" data-key="1560336942709" data-time="1560336942709" class="group/entry">
|
||||||
|
<div data-v-cf9ff940="" class="flex min-h-[1px] flex-1 content-center justify-center p-2"><span class="loading loading-bars loading-md text-primary" style="display: none;"></span></div>
|
||||||
|
</li>
|
||||||
<li data-v-cf9ff940="" data-key="1" data-time="1560336942459" class="group/entry">
|
<li data-v-cf9ff940="" data-key="1" data-time="1560336942459" class="group/entry">
|
||||||
<div data-v-cf9ff940="" class="relative flex w-full items-start gap-x-2 group-[.compact]:items-stretch">
|
<div data-v-cf9ff940="" class="relative flex w-full items-start gap-x-2 group-[.compact]:items-stretch">
|
||||||
<!--v-if-->
|
<!--v-if-->
|
||||||
@@ -24,6 +27,9 @@ exports[`<ContainerEventSource /> > render html correctly > should render dates
|
|||||||
|
|
||||||
exports[`<ContainerEventSource /> > render html correctly > should render dates with 24 hour style 1`] = `
|
exports[`<ContainerEventSource /> > render html correctly > should render dates with 24 hour style 1`] = `
|
||||||
"<ul data-v-cf9ff940="" class="group pt-4 medium" data-logs="" show-container-name="false">
|
"<ul data-v-cf9ff940="" class="group pt-4 medium" data-logs="" show-container-name="false">
|
||||||
|
<li data-v-cf9ff940="" data-key="1560336942709" data-time="1560336942709" class="group/entry">
|
||||||
|
<div data-v-cf9ff940="" class="flex min-h-[1px] flex-1 content-center justify-center p-2"><span class="loading loading-bars loading-md text-primary" style="display: none;"></span></div>
|
||||||
|
</li>
|
||||||
<li data-v-cf9ff940="" data-key="1" data-time="1560336942459" class="group/entry">
|
<li data-v-cf9ff940="" data-key="1" data-time="1560336942459" class="group/entry">
|
||||||
<div data-v-cf9ff940="" class="relative flex w-full items-start gap-x-2 group-[.compact]:items-stretch">
|
<div data-v-cf9ff940="" class="relative flex w-full items-start gap-x-2 group-[.compact]:items-stretch">
|
||||||
<!--v-if-->
|
<!--v-if-->
|
||||||
@@ -46,6 +52,9 @@ exports[`<ContainerEventSource /> > render html correctly > should render dates
|
|||||||
|
|
||||||
exports[`<ContainerEventSource /> > render html correctly > should render messages 1`] = `
|
exports[`<ContainerEventSource /> > render html correctly > should render messages 1`] = `
|
||||||
"<ul data-v-cf9ff940="" class="group pt-4 medium" data-logs="" show-container-name="false">
|
"<ul data-v-cf9ff940="" class="group pt-4 medium" data-logs="" show-container-name="false">
|
||||||
|
<li data-v-cf9ff940="" data-key="1560336942709" data-time="1560336942709" class="group/entry">
|
||||||
|
<div data-v-cf9ff940="" class="flex min-h-[1px] flex-1 content-center justify-center p-2"><span class="loading loading-bars loading-md text-primary" style="display: none;"></span></div>
|
||||||
|
</li>
|
||||||
<li data-v-cf9ff940="" data-key="1" data-time="1560336942459" class="group/entry">
|
<li data-v-cf9ff940="" data-key="1" data-time="1560336942459" class="group/entry">
|
||||||
<div data-v-cf9ff940="" class="relative flex w-full items-start gap-x-2 group-[.compact]:items-stretch">
|
<div data-v-cf9ff940="" class="relative flex w-full items-start gap-x-2 group-[.compact]:items-stretch">
|
||||||
<!--v-if-->
|
<!--v-if-->
|
||||||
@@ -67,14 +76,14 @@ exports[`<ContainerEventSource /> > render html correctly > should render messag
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`<ContainerEventSource /> > should parse messages 1`] = `
|
exports[`<ContainerEventSource /> > should parse messages 1`] = `
|
||||||
SimpleLogEntry {
|
LoadMoreLogEntry {
|
||||||
"_message": "This is a message.",
|
"_message": "",
|
||||||
"containerID": undefined,
|
"containerID": "",
|
||||||
"date": 2019-06-12T10:55:42.459Z,
|
"date": 2019-06-12T10:55:42.709Z,
|
||||||
"id": 1,
|
"id": 1560336942709,
|
||||||
"level": undefined,
|
"level": undefined,
|
||||||
"position": undefined,
|
"loader": [Function],
|
||||||
"rawMessage": "This is a message.",
|
"rawMessage": "info",
|
||||||
"std": "stderr",
|
"std": "stderr",
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import {
|
|||||||
ContainerEventLogEntry,
|
ContainerEventLogEntry,
|
||||||
ComplexLogEntry,
|
ComplexLogEntry,
|
||||||
SkippedLogsEntry,
|
SkippedLogsEntry,
|
||||||
|
LoadMoreLogEntry,
|
||||||
} from "@/models/LogEntry";
|
} from "@/models/LogEntry";
|
||||||
import { Service, Stack } from "@/models/Stack";
|
import { Service, Stack } from "@/models/Stack";
|
||||||
import { Container, GroupedContainers } from "@/models/Container";
|
import { Container, GroupedContainers } from "@/models/Container";
|
||||||
@@ -60,6 +61,8 @@ function useLogStream(url: Ref<string>, loadMoreUrl?: Ref<string>) {
|
|||||||
const loading = ref(true);
|
const loading = ref(true);
|
||||||
const error = ref(false);
|
const error = ref(false);
|
||||||
const { paused: scrollingPaused } = useScrollContext();
|
const { paused: scrollingPaused } = useScrollContext();
|
||||||
|
const { streamConfig, hasComplexLogs, levels, loadingMore } = useLoggingContext();
|
||||||
|
let initial = true;
|
||||||
|
|
||||||
function flushNow() {
|
function flushNow() {
|
||||||
if (messages.value.length + buffer.value.length > config.maxLogs) {
|
if (messages.value.length + buffer.value.length > config.maxLogs) {
|
||||||
@@ -86,9 +89,15 @@ function useLogStream(url: Ref<string>, loadMoreUrl?: Ref<string>) {
|
|||||||
buffer.value = [];
|
buffer.value = [];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (messages.value.length == 0) {
|
if (initial) {
|
||||||
// sort the buffer the very first time because of multiple logs in parallel
|
// sort the buffer the very first time because of multiple logs in parallel
|
||||||
buffer.value.sort((a, b) => a.date.getTime() - b.date.getTime());
|
buffer.value.sort((a, b) => a.date.getTime() - b.date.getTime());
|
||||||
|
|
||||||
|
if (loadMoreUrl) {
|
||||||
|
const loadMoreItem = new LoadMoreLogEntry(new Date(), loadOlderLogs);
|
||||||
|
messages.value = [loadMoreItem];
|
||||||
|
}
|
||||||
|
initial = false;
|
||||||
}
|
}
|
||||||
messages.value = [...messages.value, ...buffer.value];
|
messages.value = [...messages.value, ...buffer.value];
|
||||||
buffer.value = [];
|
buffer.value = [];
|
||||||
@@ -110,8 +119,6 @@ function useLogStream(url: Ref<string>, loadMoreUrl?: Ref<string>) {
|
|||||||
buffer.value = [];
|
buffer.value = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const { streamConfig, hasComplexLogs, levels } = useLoggingContext();
|
|
||||||
|
|
||||||
const params = computed(() => {
|
const params = computed(() => {
|
||||||
const params = new URLSearchParams();
|
const params = new URLSearchParams();
|
||||||
if (streamConfig.value.stdout) params.append("stdout", "1");
|
if (streamConfig.value.stdout) params.append("stdout", "1");
|
||||||
@@ -131,6 +138,7 @@ function useLogStream(url: Ref<string>, loadMoreUrl?: Ref<string>) {
|
|||||||
opened.value = false;
|
opened.value = false;
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
error.value = false;
|
error.value = false;
|
||||||
|
initial = true;
|
||||||
es = new EventSource(urlWithParams.value);
|
es = new EventSource(urlWithParams.value);
|
||||||
es.addEventListener("container-event", (e) => {
|
es.addEventListener("container-event", (e) => {
|
||||||
const event = JSON.parse((e as MessageEvent).data) as {
|
const event = JSON.parse((e as MessageEvent).data) as {
|
||||||
@@ -174,14 +182,13 @@ function useLogStream(url: Ref<string>, loadMoreUrl?: Ref<string>) {
|
|||||||
|
|
||||||
watch(urlWithParams, () => connect(), { immediate: true });
|
watch(urlWithParams, () => connect(), { immediate: true });
|
||||||
|
|
||||||
const isLoadingMore = ref(false);
|
|
||||||
|
|
||||||
async function loadBetween(from: Date, to: Date, lastSeenId: number, minimum: number = 0) {
|
async function loadBetween(from: Date, to: Date, lastSeenId: number, minimum: number = 0) {
|
||||||
|
if (!loadMoreUrl) throw new Error("No loadMoreUrl");
|
||||||
const abortController = new AbortController();
|
const abortController = new AbortController();
|
||||||
const signal = abortController.signal;
|
const signal = abortController.signal;
|
||||||
if (isLoadingMore.value) throw new Error("Already loading");
|
if (loadingMore.value) throw new Error("Already loading");
|
||||||
try {
|
try {
|
||||||
isLoadingMore.value = true;
|
loadingMore.value = true;
|
||||||
const urlWithMoreParams = computed(() => {
|
const urlWithMoreParams = computed(() => {
|
||||||
const loadMoreParams = new URLSearchParams(params.value);
|
const loadMoreParams = new URLSearchParams(params.value);
|
||||||
loadMoreParams.append("from", from.toISOString());
|
loadMoreParams.append("from", from.toISOString());
|
||||||
@@ -204,21 +211,24 @@ function useLogStream(url: Ref<string>, loadMoreUrl?: Ref<string>) {
|
|||||||
signal,
|
signal,
|
||||||
};
|
};
|
||||||
} finally {
|
} finally {
|
||||||
isLoadingMore.value = false;
|
loadingMore.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function loadOlderLogs() {
|
async function loadOlderLogs(entry: LoadMoreLogEntry) {
|
||||||
if (!loadMoreUrl) throw new Error("No loadMoreUrl");
|
if (!loadMoreUrl) throw new Error("No loadMoreUrl");
|
||||||
const to = messages.value[0].date;
|
if (!(messages.value[0] instanceof LoadMoreLogEntry)) throw new Error("No loadMoreLogEntry on first item");
|
||||||
const lastSeenId = messages.value[0].id;
|
|
||||||
|
const [loader, ...existingLogs] = messages.value;
|
||||||
|
const to = existingLogs[0].date;
|
||||||
|
const lastSeenId = existingLogs[0].id;
|
||||||
const last = messages.value[Math.min(messages.value.length - 1, 300)].date;
|
const last = messages.value[Math.min(messages.value.length - 1, 300)].date;
|
||||||
const delta = to.getTime() - last.getTime();
|
const delta = to.getTime() - last.getTime();
|
||||||
const from = new Date(to.getTime() + delta);
|
const from = new Date(to.getTime() + delta);
|
||||||
try {
|
try {
|
||||||
const { logs, signal } = await loadBetween(from, to, lastSeenId, 100);
|
const { logs: newLogs, signal } = await loadBetween(from, to, lastSeenId, 100);
|
||||||
if (logs && signal.aborted === false) {
|
if (newLogs && signal.aborted === false) {
|
||||||
messages.value = [...logs, ...messages.value];
|
messages.value = [loader, ...newLogs, ...existingLogs];
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
@@ -251,7 +261,6 @@ function useLogStream(url: Ref<string>, loadMoreUrl?: Ref<string>) {
|
|||||||
return {
|
return {
|
||||||
messages,
|
messages,
|
||||||
loadOlderLogs,
|
loadOlderLogs,
|
||||||
isLoadingMore,
|
|
||||||
hasComplexLogs,
|
hasComplexLogs,
|
||||||
opened,
|
opened,
|
||||||
error,
|
error,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
type ScrollContext = {
|
type ScrollContext = {
|
||||||
loading: boolean;
|
|
||||||
paused: boolean;
|
paused: boolean;
|
||||||
progress: number;
|
progress: number;
|
||||||
currentDate: Date;
|
currentDate: Date;
|
||||||
@@ -9,20 +8,18 @@ type ScrollContext = {
|
|||||||
export const scrollContextKey = Symbol("scrollContext") as InjectionKey<ScrollContext>;
|
export const scrollContextKey = Symbol("scrollContext") as InjectionKey<ScrollContext>;
|
||||||
|
|
||||||
export const provideScrollContext = () => {
|
export const provideScrollContext = () => {
|
||||||
const context = defauleValue();
|
const context = defaultValue();
|
||||||
provide(scrollContextKey, context);
|
provide(scrollContextKey, context);
|
||||||
return context;
|
return context;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useScrollContext = () => {
|
export const useScrollContext = () => {
|
||||||
const defaultValue = defauleValue();
|
const context = inject(scrollContextKey, defaultValue());
|
||||||
const context = inject(scrollContextKey, defaultValue);
|
|
||||||
return toRefs(context);
|
return toRefs(context);
|
||||||
};
|
};
|
||||||
|
|
||||||
function defauleValue() {
|
function defaultValue() {
|
||||||
return reactive({
|
return reactive({
|
||||||
loading: false,
|
|
||||||
paused: false,
|
paused: false,
|
||||||
progress: 1,
|
progress: 1,
|
||||||
currentDate: new Date(),
|
currentDate: new Date(),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import ComplexLogItem from "@/components/LogViewer/ComplexLogItem.vue";
|
|||||||
import SimpleLogItem from "@/components/LogViewer/SimpleLogItem.vue";
|
import SimpleLogItem from "@/components/LogViewer/SimpleLogItem.vue";
|
||||||
import ContainerEventLogItem from "@/components/LogViewer/ContainerEventLogItem.vue";
|
import ContainerEventLogItem from "@/components/LogViewer/ContainerEventLogItem.vue";
|
||||||
import SkippedEntriesLogItem from "@/components/LogViewer/SkippedEntriesLogItem.vue";
|
import SkippedEntriesLogItem from "@/components/LogViewer/SkippedEntriesLogItem.vue";
|
||||||
|
import LoadMoreLogItem from "@/components/LogViewer/LoadMoreLogItem.vue";
|
||||||
|
|
||||||
export type JSONValue = string | number | boolean | JSONObject | Array<JSONValue>;
|
export type JSONValue = string | number | boolean | JSONObject | Array<JSONValue>;
|
||||||
export type JSONObject = { [x: string]: JSONValue };
|
export type JSONObject = { [x: string]: JSONValue };
|
||||||
@@ -188,6 +189,23 @@ export class SkippedLogsEntry extends LogEntry<string> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class LoadMoreLogEntry extends LogEntry<string> {
|
||||||
|
constructor(
|
||||||
|
date: Date,
|
||||||
|
private readonly loader: (i: LoadMoreLogEntry) => Promise<void>,
|
||||||
|
) {
|
||||||
|
super("", "", date.getTime(), date, "stderr", "info");
|
||||||
|
}
|
||||||
|
|
||||||
|
getComponent(): Component {
|
||||||
|
return LoadMoreLogItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
async loadMore(): Promise<void> {
|
||||||
|
await this.loader(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function asLogEntry(event: LogEvent): LogEntry<string | JSONObject> {
|
export function asLogEntry(event: LogEvent): LogEntry<string | JSONObject> {
|
||||||
if (isObject(event.m)) {
|
if (isObject(event.m)) {
|
||||||
return new ComplexLogEntry(
|
return new ComplexLogEntry(
|
||||||
|
|||||||
Reference in New Issue
Block a user