From f7a7a66fcd33f8b9984fe58218cfd3ba191c555b Mon Sep 17 00:00:00 2001 From: Suhail Kakar Date: Wed, 28 Feb 2024 22:30:22 +0530 Subject: [PATCH 1/6] wip: update getwebhook logs --- .../www/components/WebhookDetails/index.tsx | 21 ++----- .../www/hooks/use-api/endpoints/webhook.ts | 57 +++++++++++++++---- .../dashboard/developers/webhooks/[id].tsx | 3 +- 3 files changed, 51 insertions(+), 30 deletions(-) diff --git a/packages/www/components/WebhookDetails/index.tsx b/packages/www/components/WebhookDetails/index.tsx index 5a540abad7..99230d8697 100644 --- a/packages/www/components/WebhookDetails/index.tsx +++ b/packages/www/components/WebhookDetails/index.tsx @@ -260,13 +260,8 @@ const WebhookDetails = ({ id, data, logs, handleLogFilters, refetchLogs }) => { - {logs.length > 0 ? ( - + {logs?.data?.length > 0 ? ( + ) : ( { }; const Filters = ({ filters, activeFilter, handleFilterClick, logs }) => { - const totalWebhookLogs = logs?.length; - - const totalSucceededWebhookLogs = logs?.filter((log) => log.success).length; - - const totalFailedWebhookLogs = logs?.filter((log) => !log.success).length; - return ( { color: activeFilter === filter && "$blue11", }}> {filter === "all" - ? totalWebhookLogs + ? logs?.totalCount : filter === "succeeded" - ? totalSucceededWebhookLogs - : totalFailedWebhookLogs} + ? logs?.successCount + : logs?.failedCount} ))} diff --git a/packages/www/hooks/use-api/endpoints/webhook.ts b/packages/www/hooks/use-api/endpoints/webhook.ts index 9349c616ae..1297c701d8 100644 --- a/packages/www/hooks/use-api/endpoints/webhook.ts +++ b/packages/www/hooks/use-api/endpoints/webhook.ts @@ -105,19 +105,52 @@ export const deleteWebhooks = async (ids: Array): Promise => { export const getWebhookLogs = async ( webhookId, - filters = null -): Promise => { - const f = filters ? JSON.stringify(filters) : undefined; + filters = [], + cursor, + count +) => { + const buildFilters = (additionalFilters) => [ + ...filters, + ...additionalFilters, + ]; - const [res, logs] = await context.fetch( - `/webhook/${webhookId}/log?${qs.stringify({ filters: f })}` - ); - if (res.status !== 200) { - throw logs && typeof logs === "object" - ? { ...logs, status: res.status } - : new Error(logs); - } - return logs; + const fetchLogs = async (additionalFilters = [], limit = 10) => { + const query = qs.stringify({ + limit, + cursor, + count, + filters: JSON.stringify( + additionalFilters.length > 0 ? buildFilters(additionalFilters) : filters + ), + }); + const [res, data] = await context.fetch( + `/webhook/${webhookId}/log?${query}` + ); + if (res.status !== 200) { + throw data && typeof data === "object" + ? { ...data, status: res.status } + : new Error(data); + } + return { + data, + count: res.headers.get("X-Total-Count"), + cursor: getCursor(res.headers.get("link")), + }; + }; + + const [allLogs, failedLogs, successLogs] = await Promise.all([ + fetchLogs([]), + fetchLogs([{ id: "success", value: "false" }], 1), + fetchLogs([{ id: "success", value: "true" }], 1), + ]); + + return { + data: allLogs.data, + curoser: allLogs.cursor, + totalCount: allLogs.count, + failedCount: failedLogs.count, + successCount: successLogs.count, + }; }; export const resendWebhook = async (params: { diff --git a/packages/www/pages/dashboard/developers/webhooks/[id].tsx b/packages/www/pages/dashboard/developers/webhooks/[id].tsx index e461a028e5..d109ece13e 100644 --- a/packages/www/pages/dashboard/developers/webhooks/[id].tsx +++ b/packages/www/pages/dashboard/developers/webhooks/[id].tsx @@ -25,10 +25,9 @@ const WebhookDetail = () => { const { data: logs, refetch: refetchLogs } = useQuery( ["webhookLogs", id, logFilters], - () => getWebhookLogs(id, logFilters), + () => getWebhookLogs(id, logFilters, null, true), { enabled: !!id, - initialData: [], } ); From e21245ecc08d4905ead9fef30d5c3e60caf778f1 Mon Sep 17 00:00:00 2001 From: Suhail Kakar Date: Wed, 28 Feb 2024 23:34:57 +0530 Subject: [PATCH 2/6] update filter components --- .../WebhookDetails/LogsContainer.tsx | 17 +--------- .../www/components/WebhookDetails/index.tsx | 7 ++++ .../www/hooks/use-api/endpoints/webhook.ts | 10 +++--- .../dashboard/developers/webhooks/[id].tsx | 33 +++++++++++++++++-- 4 files changed, 43 insertions(+), 24 deletions(-) diff --git a/packages/www/components/WebhookDetails/LogsContainer.tsx b/packages/www/components/WebhookDetails/LogsContainer.tsx index d453656ce4..15f9876b0c 100644 --- a/packages/www/components/WebhookDetails/LogsContainer.tsx +++ b/packages/www/components/WebhookDetails/LogsContainer.tsx @@ -25,12 +25,10 @@ const Cell = styled(Text, { const LogsContainer = ({ data, logs, - filter, refetchLogs, }: { data: Webhook; logs: WebhookLogs[]; - filter: FilterType; refetchLogs(): Promise; }) => { const { resendWebhook } = useApi(); @@ -38,19 +36,6 @@ const LogsContainer = ({ const [selected, setSelected] = useState(logs[0]); const [isResending, setIsResending] = useState(false); - const succeededLogs = logs?.filter((log) => log.success); - - const failedLogs = logs?.filter((log) => !log.success); - - const router = useRouter(); - - const renderedLogs = - filter === "all" - ? logs - : filter === "succeeded" - ? succeededLogs - : failedLogs; - const customTheme = { key: "color:#606060;line-height:1.8;font-size:14px;", string: "color:#DABAAB;font-size:14px", @@ -101,7 +86,7 @@ const LogsContainer = ({ borderRight: "1px solid $colors$neutral6", height: "calc(100vh - 450px)", }}> - {renderedLogs.map((log: WebhookLogs, index) => ( + {logs.map((log: WebhookLogs, index) => ( setSelected(log)} key={log.id} diff --git a/packages/www/components/WebhookDetails/index.tsx b/packages/www/components/WebhookDetails/index.tsx index 99230d8697..c0004d1e5a 100644 --- a/packages/www/components/WebhookDetails/index.tsx +++ b/packages/www/components/WebhookDetails/index.tsx @@ -90,6 +90,13 @@ const WebhookDetails = ({ id, data, logs, handleLogFilters, refetchLogs }) => { const handleFilterClick = (filter: FilterType) => { setActiveFilter(filter); + handleLogFilters( + filter === "all" + ? [] + : filter === "succeeded" + ? [{ id: "success", value: "true" }] + : [{ id: "success", value: "false" }] + ); }; const revealSecretHandler = () => { diff --git a/packages/www/hooks/use-api/endpoints/webhook.ts b/packages/www/hooks/use-api/endpoints/webhook.ts index 1297c701d8..acfe516e77 100644 --- a/packages/www/hooks/use-api/endpoints/webhook.ts +++ b/packages/www/hooks/use-api/endpoints/webhook.ts @@ -114,7 +114,7 @@ export const getWebhookLogs = async ( ...additionalFilters, ]; - const fetchLogs = async (additionalFilters = [], limit = 10) => { + const fetchLogs = async (additionalFilters = [], limit = 20) => { const query = qs.stringify({ limit, cursor, @@ -146,10 +146,10 @@ export const getWebhookLogs = async ( return { data: allLogs.data, - curoser: allLogs.cursor, - totalCount: allLogs.count, - failedCount: failedLogs.count, - successCount: successLogs.count, + cursor: allLogs.cursor, + totalCount: allLogs.count || 0, + failedCount: failedLogs.count || 0, + successCount: successLogs.count || 0, }; }; diff --git a/packages/www/pages/dashboard/developers/webhooks/[id].tsx b/packages/www/pages/dashboard/developers/webhooks/[id].tsx index d109ece13e..613b67ad17 100644 --- a/packages/www/pages/dashboard/developers/webhooks/[id].tsx +++ b/packages/www/pages/dashboard/developers/webhooks/[id].tsx @@ -9,7 +9,8 @@ import { DashboardWebhooks as Content } from "content"; const WebhookDetail = () => { useLoggedIn(); const { user } = useApi(); - const [logFilters, setLogFilters] = useState(); + const [logFilters, setLogFilters] = useState([]); + const [logs, setLogs] = useState(); const { getWebhook, getWebhookLogs } = useApi(); const router = useRouter(); @@ -23,16 +24,42 @@ const WebhookDetail = () => { } ); - const { data: logs, refetch: refetchLogs } = useQuery( + const { data, refetch: refetchLogs } = useQuery( ["webhookLogs", id, logFilters], () => getWebhookLogs(id, logFilters, null, true), { enabled: !!id, + onSuccess: (data) => { + const containsSuccessFilter = logFilters.some( + (filter) => filter.id === "success" + ); + if (containsSuccessFilter) { + setLogs({ + ...data, + totalCount: logs.totalCount, + failedCount: logs.failedCount, + successCount: logs.successCount, + }); + } else { + setLogs(data); + } + }, } ); const handleLogFilters = async (filters) => { - setLogFilters(filters); + if (filters.length === 0) { + setLogFilters([]); + refetchLogs(); + return; + } + + const newFilters = logFilters.filter( + (existingFilter) => + !filters.some((newFilter) => newFilter.id === existingFilter.id) + ); + + setLogFilters([...newFilters, ...filters]); refetchLogs(); }; From 7b4e17ec0665ead4f410a489556206507c35c235 Mon Sep 17 00:00:00 2001 From: Suhail Kakar Date: Thu, 29 Feb 2024 00:56:42 +0530 Subject: [PATCH 3/6] added infinite scroll option --- .../WebhookDetails/LogsContainer.tsx | 53 ++++++++++++++++--- .../www/components/WebhookDetails/index.tsx | 18 ++++++- .../www/hooks/use-api/endpoints/webhook.ts | 11 ++-- .../dashboard/developers/webhooks/[id].tsx | 31 +++++++++-- 4 files changed, 94 insertions(+), 19 deletions(-) diff --git a/packages/www/components/WebhookDetails/LogsContainer.tsx b/packages/www/components/WebhookDetails/LogsContainer.tsx index 15f9876b0c..2c485c7d6f 100644 --- a/packages/www/components/WebhookDetails/LogsContainer.tsx +++ b/packages/www/components/WebhookDetails/LogsContainer.tsx @@ -6,15 +6,15 @@ import { Flex, Button, } from "@livepeer/design-system"; +import { useEffect, useRef } from "react"; import moment from "moment"; import { CheckIcon, Cross1Icon } from "@radix-ui/react-icons"; import { useState } from "react"; import { WebhookLogs } from "hooks/use-api/types"; import JSONPretty from "react-json-pretty"; import { useApi } from "hooks"; -import { useRouter } from "next/navigation"; import { Webhook } from "@livepeer.studio/api"; -import { FilterType } from "./index"; +import Spinner from "components/Spinner"; const Cell = styled(Text, { py: "$2", @@ -22,26 +22,31 @@ const Cell = styled(Text, { fontSize: "$3", }); +const customTheme = { + key: "color:#606060;line-height:1.8;font-size:14px;", + string: "color:#DABAAB;font-size:14px", + value: "color:#788570;font-size:14px", + boolean: "color:#788570;font-size:14px", +}; + const LogsContainer = ({ data, logs, refetchLogs, + loadMore, + isLogsLoading, }: { data: Webhook; logs: WebhookLogs[]; refetchLogs(): Promise; + loadMore(): void; }) => { const { resendWebhook } = useApi(); const [selected, setSelected] = useState(logs[0]); const [isResending, setIsResending] = useState(false); - const customTheme = { - key: "color:#606060;line-height:1.8;font-size:14px;", - string: "color:#DABAAB;font-size:14px", - value: "color:#788570;font-size:14px", - boolean: "color:#788570;font-size:14px", - }; + const logsContainerRef = useRef(null); const onResend = async (log: WebhookLogs) => { setIsResending(true); @@ -56,6 +61,26 @@ const LogsContainer = ({ } }; + const handleScroll = () => { + const { scrollTop, scrollHeight, clientHeight } = logsContainerRef.current; + if (scrollTop + clientHeight >= scrollHeight) { + loadMore(); + } + }; + + useEffect(() => { + const scrollContainer = logsContainerRef.current; + if (scrollContainer) { + scrollContainer.addEventListener("scroll", handleScroll); + } + + return () => { + if (scrollContainer) { + scrollContainer.removeEventListener("scroll", handleScroll); + } + }; + }, [loadMore]); + return ( ))} + {isLogsLoading && ( + + + + )} { +const WebhookDetails = ({ + id, + data, + logs, + handleLogFilters, + refetchLogs, + loadMore, + isLogsLoading, +}) => { const { deleteWebhook, updateWebhook } = useApi(); const [deleting, setDeleting] = useState(false); const [deleteDialogOpen, setDeleteDialogOpen] = useState(false); @@ -268,7 +276,13 @@ const WebhookDetails = ({ id, data, logs, handleLogFilters, refetchLogs }) => { {logs?.data?.length > 0 ? ( - + ) : ( { + const fetchLogs = async (fromStatus, additionalFilters = [], limit = 20) => { + console.log("fromStatus", additionalFilters); const query = qs.stringify({ limit, - cursor, + cursor: fromStatus ? null : cursor, count, filters: JSON.stringify( additionalFilters.length > 0 ? buildFilters(additionalFilters) : filters @@ -139,9 +140,9 @@ export const getWebhookLogs = async ( }; const [allLogs, failedLogs, successLogs] = await Promise.all([ - fetchLogs([]), - fetchLogs([{ id: "success", value: "false" }], 1), - fetchLogs([{ id: "success", value: "true" }], 1), + fetchLogs(false, []), + fetchLogs(true, [{ id: "success", value: "false" }], 1), + fetchLogs(true, [{ id: "success", value: "true" }], 1), ]); return { diff --git a/packages/www/pages/dashboard/developers/webhooks/[id].tsx b/packages/www/pages/dashboard/developers/webhooks/[id].tsx index 613b67ad17..69df9fa3c4 100644 --- a/packages/www/pages/dashboard/developers/webhooks/[id].tsx +++ b/packages/www/pages/dashboard/developers/webhooks/[id].tsx @@ -10,7 +10,14 @@ const WebhookDetail = () => { useLoggedIn(); const { user } = useApi(); const [logFilters, setLogFilters] = useState([]); - const [logs, setLogs] = useState(); + const [logs, setLogs] = useState({ + data: [], + cursor: null, + totalCount: 0, + failedCount: 0, + successCount: 0, + }); + const [loadingMore, setLoadingMore] = useState(false); const { getWebhook, getWebhookLogs } = useApi(); const router = useRouter(); @@ -24,25 +31,32 @@ const WebhookDetail = () => { } ); - const { data, refetch: refetchLogs } = useQuery( + const { refetch: refetchLogs, isLoading: isLogsLoading } = useQuery( ["webhookLogs", id, logFilters], - () => getWebhookLogs(id, logFilters, null, true), + () => getWebhookLogs(id, logFilters, logs ? logs.cursor : null, true), { enabled: !!id, onSuccess: (data) => { const containsSuccessFilter = logFilters.some( (filter) => filter.id === "success" ); + if (containsSuccessFilter) { setLogs({ ...data, + data: loadingMore ? [...logs.data, ...data.data] : data.data, totalCount: logs.totalCount, failedCount: logs.failedCount, successCount: logs.successCount, }); } else { - setLogs(data); + setLogs({ + ...data, + data: loadingMore ? [...logs.data, ...data.data] : data.data, + }); } + + setLoadingMore(false); }, } ); @@ -67,6 +81,13 @@ const WebhookDetail = () => { return ; } + const loadMore = () => { + if (logs.cursor) { + setLoadingMore(true); + refetchLogs(); + } + }; + return ( { data={webhookData} logs={logs} refetchLogs={refetchLogs} + loadMore={loadMore} + isLogsLoading={isLogsLoading} /> ); From 7f6c995eb6e08380a90c8f9a2a3c42c8ac3ce407 Mon Sep 17 00:00:00 2001 From: Suhail Kakar Date: Thu, 29 Feb 2024 01:00:58 +0530 Subject: [PATCH 4/6] add type --- packages/www/components/WebhookDetails/LogsContainer.tsx | 1 + packages/www/lib/utils/index.tsx | 8 +------- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/www/components/WebhookDetails/LogsContainer.tsx b/packages/www/components/WebhookDetails/LogsContainer.tsx index 2c485c7d6f..65b2b77986 100644 --- a/packages/www/components/WebhookDetails/LogsContainer.tsx +++ b/packages/www/components/WebhookDetails/LogsContainer.tsx @@ -40,6 +40,7 @@ const LogsContainer = ({ logs: WebhookLogs[]; refetchLogs(): Promise; loadMore(): void; + isLogsLoading: boolean; }) => { const { resendWebhook } = useApi(); diff --git a/packages/www/lib/utils/index.tsx b/packages/www/lib/utils/index.tsx index fe83172637..1a3a954115 100644 --- a/packages/www/lib/utils/index.tsx +++ b/packages/www/lib/utils/index.tsx @@ -236,13 +236,7 @@ export const CARD_OPTIONS = { }; export function isStaging(): boolean { - return ( - typeof window !== "undefined" && - (window.location.hostname.includes("livepeer.monster") || - window.location.hostname.includes("livepeer.vercel.app") || - window.location.hostname.includes("livepeerorg.vercel.app") || - window.location.hostname.includes("livepeerorg.now.sh")) - ); + return true; } export function isDevelopment(): boolean { From 733176233b0f6faba3cae851e82a3a3d67fe0b85 Mon Sep 17 00:00:00 2001 From: Suhail Kakar Date: Mon, 4 Mar 2024 18:38:03 +0530 Subject: [PATCH 5/6] =?UTF-8?q?revert=20=F0=9F=A4=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/www/lib/utils/index.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/packages/www/lib/utils/index.tsx b/packages/www/lib/utils/index.tsx index 1a3a954115..fe83172637 100644 --- a/packages/www/lib/utils/index.tsx +++ b/packages/www/lib/utils/index.tsx @@ -236,7 +236,13 @@ export const CARD_OPTIONS = { }; export function isStaging(): boolean { - return true; + return ( + typeof window !== "undefined" && + (window.location.hostname.includes("livepeer.monster") || + window.location.hostname.includes("livepeer.vercel.app") || + window.location.hostname.includes("livepeerorg.vercel.app") || + window.location.hostname.includes("livepeerorg.now.sh")) + ); } export function isDevelopment(): boolean { From bb4da7d574f3b54216b22a2f89d60147a8cb7152 Mon Sep 17 00:00:00 2001 From: Suhail Kakar Date: Mon, 4 Mar 2024 19:12:26 +0530 Subject: [PATCH 6/6] new updates --- .../www/hooks/use-api/endpoints/webhook.ts | 1 - .../dashboard/developers/webhooks/[id].tsx | 23 ++++++++++++++----- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/www/hooks/use-api/endpoints/webhook.ts b/packages/www/hooks/use-api/endpoints/webhook.ts index 54b42e9331..08dacb93f5 100644 --- a/packages/www/hooks/use-api/endpoints/webhook.ts +++ b/packages/www/hooks/use-api/endpoints/webhook.ts @@ -115,7 +115,6 @@ export const getWebhookLogs = async ( ]; const fetchLogs = async (fromStatus, additionalFilters = [], limit = 20) => { - console.log("fromStatus", additionalFilters); const query = qs.stringify({ limit, cursor: fromStatus ? null : cursor, diff --git a/packages/www/pages/dashboard/developers/webhooks/[id].tsx b/packages/www/pages/dashboard/developers/webhooks/[id].tsx index 69df9fa3c4..ad10a46e12 100644 --- a/packages/www/pages/dashboard/developers/webhooks/[id].tsx +++ b/packages/www/pages/dashboard/developers/webhooks/[id].tsx @@ -18,7 +18,6 @@ const WebhookDetail = () => { successCount: 0, }); const [loadingMore, setLoadingMore] = useState(false); - const { getWebhook, getWebhookLogs } = useApi(); const router = useRouter(); const { id } = router.query; @@ -31,17 +30,25 @@ const WebhookDetail = () => { } ); + const containsSuccessFilter = (logFilters) => { + return logFilters.some((filter) => filter.id === "success"); + }; + const { refetch: refetchLogs, isLoading: isLogsLoading } = useQuery( ["webhookLogs", id, logFilters], - () => getWebhookLogs(id, logFilters, logs ? logs.cursor : null, true), + () => + getWebhookLogs( + id, + logFilters, + logFilters.length > 0 ? null : logs.cursor, + true + ), { enabled: !!id, onSuccess: (data) => { - const containsSuccessFilter = logFilters.some( - (filter) => filter.id === "success" - ); + const isSuccess = containsSuccessFilter(logFilters); - if (containsSuccessFilter) { + if (isSuccess) { setLogs({ ...data, data: loadingMore ? [...logs.data, ...data.data] : data.data, @@ -64,6 +71,10 @@ const WebhookDetail = () => { const handleLogFilters = async (filters) => { if (filters.length === 0) { setLogFilters([]); + setLogs({ + ...logs, + cursor: null, + }); refetchLogs(); return; }