diff --git a/apps/dashboard/app/(app)/logs-v2/components/charts/index.tsx b/apps/dashboard/app/(app)/logs-v2/components/charts/index.tsx
index 62785edb85..ab5a675205 100644
--- a/apps/dashboard/app/(app)/logs-v2/components/charts/index.tsx
+++ b/apps/dashboard/app/(app)/logs-v2/components/charts/index.tsx
@@ -33,7 +33,7 @@ const formatTimestampTooltip = (value: string | number) => {
const date = new Date(value);
const offset = new Date().getTimezoneOffset() * -1;
const localDate = addMinutes(date, offset);
- return format(localDate, "MMM dd HH:mm:ss.SS aa");
+ return format(localDate, "MMM dd HH:mm aa");
};
const formatTimestampLabel = (timestamp: string | number | Date) => {
diff --git a/apps/dashboard/app/(app)/logs-v2/components/control-cloud/index.tsx b/apps/dashboard/app/(app)/logs-v2/components/control-cloud/index.tsx
index e4fb5e946d..7c5bbd1c26 100644
--- a/apps/dashboard/app/(app)/logs-v2/components/control-cloud/index.tsx
+++ b/apps/dashboard/app/(app)/logs-v2/components/control-cloud/index.tsx
@@ -27,11 +27,11 @@ const formatValue = (value: string | number): string => {
const statusFamily = Math.floor(Number.parseInt(value) / 100);
switch (statusFamily) {
case 5:
- return "5XX (Error)";
+ return "5xx (Error)";
case 4:
- return "4XX (Warning)";
+ return "4xx (Warning)";
case 2:
- return "2XX (Success)";
+ return "2xx (Success)";
default:
return `${statusFamily}xx`;
}
@@ -106,6 +106,10 @@ export const ControlCloud = () => {
updateFilters([]);
});
+ useKeyboardShortcut({ key: "c", meta: true }, () => {
+ setFocusedIndex(0);
+ });
+
const handleRemoveFilter = useCallback(
(id: string) => {
removeFilter(id);
@@ -192,7 +196,7 @@ export const ControlCloud = () => {
return (
{filters.map((filter, index) => (
@@ -205,9 +209,12 @@ export const ControlCloud = () => {
index={index}
/>
))}
-
+
Clear filters
+
+
Focus filters
+
);
diff --git a/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-display/components/display-popover.tsx b/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-display/components/display-popover.tsx
new file mode 100644
index 0000000000..db6e699603
--- /dev/null
+++ b/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-display/components/display-popover.tsx
@@ -0,0 +1,169 @@
+import { isDisplayProperty, useLogsContext } from "@/app/(app)/logs-v2/context/logs";
+import { useKeyboardShortcut } from "@/app/(app)/logs-v2/hooks/use-keyboard-shortcut";
+import { KeyboardButton } from "@/components/keyboard-button";
+import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover";
+import {
+ type KeyboardEvent,
+ type PropsWithChildren,
+ useCallback,
+ useEffect,
+ useState,
+} from "react";
+
+const DISPLAY_PROPERTIES = [
+ { id: "time", label: "Time" },
+ { id: "response_status", label: "Status" },
+ { id: "method", label: "Method" },
+ { id: "path", label: "Path" },
+ { id: "response_body", label: "Response Body" },
+ { id: "request_id", label: "Request ID" },
+ { id: "host", label: "Host" },
+ { id: "request_headers", label: "Request Headers" },
+ { id: "request_body", label: "Request Body" },
+ { id: "response_headers", label: "Response Headers" },
+];
+
+const DisplayPropertyItem = ({
+ label,
+ selected,
+ onClick,
+ isFocused,
+ index,
+}: {
+ label: string;
+ selected: boolean;
+ onClick: () => void;
+ isFocused: boolean;
+ index: number;
+}) => (
+
{
+ if (e.key === "Enter" || e.key === " ") {
+ e.preventDefault();
+ onClick();
+ }
+ }}
+ >
+ {label}
+
+);
+
+const PopoverHeader = () => (
+
+ Display Properties...
+
+
+);
+
+export const DisplayPopover = ({ children }: PropsWithChildren) => {
+ const [open, setOpen] = useState(false);
+ const [focusedIndex, setFocusedIndex] = useState
(null);
+ const { displayProperties, toggleDisplayProperty } = useLogsContext();
+
+ useKeyboardShortcut("d", () => {
+ setOpen((prev) => !prev);
+ if (!open) {
+ setFocusedIndex(0);
+ }
+ });
+
+ const handleKeyNavigation = useCallback(
+ (e: KeyboardEvent) => {
+ const itemsPerRow = Math.floor(384 / 120); // Approximate width / item width
+ const totalItems = DISPLAY_PROPERTIES.length;
+ const currentRow = Math.floor((focusedIndex ?? 0) / itemsPerRow);
+ const currentCol = (focusedIndex ?? 0) % itemsPerRow;
+
+ const moveToIndex = (newIndex: number) => {
+ e.preventDefault();
+ setFocusedIndex(Math.max(0, Math.min(newIndex, totalItems - 1)));
+ };
+
+ switch (e.key) {
+ case "ArrowRight":
+ case "l": {
+ moveToIndex((focusedIndex ?? -1) + 1);
+ break;
+ }
+ case "ArrowLeft":
+ case "h": {
+ moveToIndex((focusedIndex ?? 1) - 1);
+ break;
+ }
+ case "ArrowDown":
+ case "j": {
+ const nextRowIndex = (currentRow + 1) * itemsPerRow + currentCol;
+ if (nextRowIndex < totalItems) {
+ moveToIndex(nextRowIndex);
+ }
+ break;
+ }
+ case "ArrowUp":
+ case "k": {
+ const prevRowIndex = (currentRow - 1) * itemsPerRow + currentCol;
+ if (prevRowIndex >= 0) {
+ moveToIndex(prevRowIndex);
+ }
+ break;
+ }
+ case "Enter":
+ case " ": {
+ if (focusedIndex !== null) {
+ const prop = DISPLAY_PROPERTIES[focusedIndex];
+ if (isDisplayProperty(prop.id)) {
+ toggleDisplayProperty(prop.id);
+ }
+ }
+ break;
+ }
+ }
+ },
+ [focusedIndex, toggleDisplayProperty],
+ );
+
+ useEffect(() => {
+ if (!open) {
+ setFocusedIndex(null);
+ }
+ }, [open]);
+
+ return (
+
+ {children}
+
+
+
+
+ {DISPLAY_PROPERTIES.map((prop, index) => (
+ {
+ if (isDisplayProperty(prop.id)) {
+ toggleDisplayProperty(prop.id);
+ }
+ }}
+ isFocused={focusedIndex === index}
+ index={index}
+ />
+ ))}
+
+
+
+
+ );
+};
+
+export default DisplayPopover;
diff --git a/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-display/index.tsx b/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-display/index.tsx
new file mode 100644
index 0000000000..c34fdda8e3
--- /dev/null
+++ b/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-display/index.tsx
@@ -0,0 +1,23 @@
+import { Sliders } from "@unkey/icons";
+import { Button } from "@unkey/ui";
+import { cn } from "@unkey/ui/src/lib/utils";
+import { DisplayPopover } from "./components/display-popover";
+
+export const LogsDisplay = () => {
+ return (
+
+
+
+
+
+ );
+};
diff --git a/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-filters/components/filter-checkbox.tsx b/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-filters/components/filter-checkbox.tsx
index 7541df11ef..97edf2abf5 100644
--- a/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-filters/components/filter-checkbox.tsx
+++ b/apps/dashboard/app/(app)/logs-v2/components/controls/components/logs-filters/components/filter-checkbox.tsx
@@ -69,7 +69,7 @@ export const FilterCheckbox = ({
>
@@ -89,7 +89,7 @@ export const FilterCheckbox =
({
{checkboxes.map((checkbox, index) => (