Phase 2: Refactor Logs cluster to MCP SDK types
Replace string-typed log levels with SDK LoggingLevel across the Logs group components and LoggingScreen. - LogControls: type currentLevel, visibleLevels, and all handlers with LoggingLevel instead of string; type LOG_LEVELS array and LEVEL_COLORS record with LoggingLevel - LogStreamPanel: type visibleLevels as Record<LoggingLevel, boolean> instead of Record<string, boolean> - LoggingScreen: type currentLevel, onSetLevel, visibleLevels state, and toggle handlers with LoggingLevel; extract NO_LEVELS_VISIBLE as a module-level constant - Stories already used LoggingLevel literals; updated type annotations to use Record<LoggingLevel, boolean> - No ConnectedView story changes needed (already passes valid LoggingLevel values) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
91e5a1257a
commit
95e3a2dca7
4 changed files with 31 additions and 20 deletions
|
|
@ -1,8 +1,9 @@
|
||||||
import type { Meta, StoryObj } from "@storybook/react-vite";
|
import type { Meta, StoryObj } from "@storybook/react-vite";
|
||||||
|
import type { LoggingLevel } from "@modelcontextprotocol/sdk/types.js";
|
||||||
import { fn } from "storybook/test";
|
import { fn } from "storybook/test";
|
||||||
import { LogControls } from "./LogControls";
|
import { LogControls } from "./LogControls";
|
||||||
|
|
||||||
const allLevelsVisible: Record<string, boolean> = {
|
const allLevelsVisible: Record<LoggingLevel, boolean> = {
|
||||||
debug: true,
|
debug: true,
|
||||||
info: true,
|
info: true,
|
||||||
notice: true,
|
notice: true,
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,9 @@ import {
|
||||||
Title,
|
Title,
|
||||||
UnstyledButton,
|
UnstyledButton,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
|
import type { LoggingLevel } from "@modelcontextprotocol/sdk/types.js";
|
||||||
|
|
||||||
const LOG_LEVELS = [
|
const LOG_LEVELS: LoggingLevel[] = [
|
||||||
"debug",
|
"debug",
|
||||||
"info",
|
"info",
|
||||||
"notice",
|
"notice",
|
||||||
|
|
@ -18,9 +19,9 @@ const LOG_LEVELS = [
|
||||||
"critical",
|
"critical",
|
||||||
"alert",
|
"alert",
|
||||||
"emergency",
|
"emergency",
|
||||||
] as const;
|
];
|
||||||
|
|
||||||
const LEVEL_COLORS: Record<string, { c: string }> = {
|
const LEVEL_COLORS: Record<LoggingLevel, { c: string }> = {
|
||||||
debug: { c: "dimmed" },
|
debug: { c: "dimmed" },
|
||||||
info: { c: "blue" },
|
info: { c: "blue" },
|
||||||
notice: { c: "teal" },
|
notice: { c: "teal" },
|
||||||
|
|
@ -37,12 +38,12 @@ const SubtleButton = Button.withProps({
|
||||||
});
|
});
|
||||||
|
|
||||||
export interface LogControlsProps {
|
export interface LogControlsProps {
|
||||||
currentLevel: string;
|
currentLevel: LoggingLevel;
|
||||||
filterText: string;
|
filterText: string;
|
||||||
visibleLevels: Record<string, boolean>;
|
visibleLevels: Record<LoggingLevel, boolean>;
|
||||||
onSetLevel: (level: string) => void;
|
onSetLevel: (level: LoggingLevel) => void;
|
||||||
onFilterChange: (text: string) => void;
|
onFilterChange: (text: string) => void;
|
||||||
onToggleLevel: (level: string, visible: boolean) => void;
|
onToggleLevel: (level: LoggingLevel, visible: boolean) => void;
|
||||||
onToggleAllLevels: () => void;
|
onToggleAllLevels: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -72,7 +73,7 @@ export function LogControls({
|
||||||
data={LOG_LEVELS.map((level) => ({ value: level, label: level }))}
|
data={LOG_LEVELS.map((level) => ({ value: level, label: level }))}
|
||||||
value={currentLevel}
|
value={currentLevel}
|
||||||
onChange={(value) => {
|
onChange={(value) => {
|
||||||
if (value) onSetLevel(value);
|
if (value) onSetLevel(value as LoggingLevel);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Button size="sm" onClick={() => onSetLevel(currentLevel)}>
|
<Button size="sm" onClick={() => onSetLevel(currentLevel)}>
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,14 @@ import {
|
||||||
Text,
|
Text,
|
||||||
Title,
|
Title,
|
||||||
} from "@mantine/core";
|
} from "@mantine/core";
|
||||||
|
import type { LoggingLevel } from "@modelcontextprotocol/sdk/types.js";
|
||||||
import { LogEntry } from "../../elements/LogEntry/LogEntry";
|
import { LogEntry } from "../../elements/LogEntry/LogEntry";
|
||||||
import type { LogEntryData } from "../../elements/LogEntry/LogEntry";
|
import type { LogEntryData } from "../../elements/LogEntry/LogEntry";
|
||||||
|
|
||||||
export interface LogStreamPanelProps {
|
export interface LogStreamPanelProps {
|
||||||
entries: LogEntryData[];
|
entries: LogEntryData[];
|
||||||
filterText: string;
|
filterText: string;
|
||||||
visibleLevels: Record<string, boolean>;
|
visibleLevels: Record<LoggingLevel, boolean>;
|
||||||
autoScroll: boolean;
|
autoScroll: boolean;
|
||||||
onToggleAutoScroll: () => void;
|
onToggleAutoScroll: () => void;
|
||||||
onCopyAll: () => void;
|
onCopyAll: () => void;
|
||||||
|
|
@ -50,7 +51,7 @@ function formatData(data: unknown): string {
|
||||||
function matchesFilters(
|
function matchesFilters(
|
||||||
entry: LogEntryData,
|
entry: LogEntryData,
|
||||||
filterText: string,
|
filterText: string,
|
||||||
visibleLevels: Record<string, boolean>,
|
visibleLevels: Record<LoggingLevel, boolean>,
|
||||||
): boolean {
|
): boolean {
|
||||||
if (!visibleLevels[entry.params.level]) return false;
|
if (!visibleLevels[entry.params.level]) return false;
|
||||||
if (filterText) {
|
if (filterText) {
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,14 @@
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Card, Flex, Stack } from "@mantine/core";
|
import { Card, Flex, Stack } from "@mantine/core";
|
||||||
|
import type { LoggingLevel } from "@modelcontextprotocol/sdk/types.js";
|
||||||
import { LogControls } from "../../groups/LogControls/LogControls";
|
import { LogControls } from "../../groups/LogControls/LogControls";
|
||||||
import { LogStreamPanel } from "../../groups/LogStreamPanel/LogStreamPanel";
|
import { LogStreamPanel } from "../../groups/LogStreamPanel/LogStreamPanel";
|
||||||
import type { LogEntryData } from "../../elements/LogEntry/LogEntry";
|
import type { LogEntryData } from "../../elements/LogEntry/LogEntry";
|
||||||
|
|
||||||
export interface LoggingScreenProps {
|
export interface LoggingScreenProps {
|
||||||
entries: LogEntryData[];
|
entries: LogEntryData[];
|
||||||
currentLevel: string;
|
currentLevel: LoggingLevel;
|
||||||
onSetLevel: (level: string) => void;
|
onSetLevel: (level: LoggingLevel) => void;
|
||||||
onClear: () => void;
|
onClear: () => void;
|
||||||
onExport: () => void;
|
onExport: () => void;
|
||||||
autoScroll: boolean;
|
autoScroll: boolean;
|
||||||
|
|
@ -15,7 +16,7 @@ export interface LoggingScreenProps {
|
||||||
onCopyAll: () => void;
|
onCopyAll: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const ALL_LEVELS_VISIBLE: Record<string, boolean> = {
|
const ALL_LEVELS_VISIBLE: Record<LoggingLevel, boolean> = {
|
||||||
debug: true,
|
debug: true,
|
||||||
info: true,
|
info: true,
|
||||||
notice: true,
|
notice: true,
|
||||||
|
|
@ -26,6 +27,17 @@ const ALL_LEVELS_VISIBLE: Record<string, boolean> = {
|
||||||
emergency: true,
|
emergency: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const NO_LEVELS_VISIBLE: Record<LoggingLevel, boolean> = {
|
||||||
|
debug: false,
|
||||||
|
info: false,
|
||||||
|
notice: false,
|
||||||
|
warning: false,
|
||||||
|
error: false,
|
||||||
|
critical: false,
|
||||||
|
alert: false,
|
||||||
|
emergency: false,
|
||||||
|
};
|
||||||
|
|
||||||
const ScreenLayout = Flex.withProps({
|
const ScreenLayout = Flex.withProps({
|
||||||
variant: "screen",
|
variant: "screen",
|
||||||
h: "calc(100vh - var(--app-shell-header-height, 0px))",
|
h: "calc(100vh - var(--app-shell-header-height, 0px))",
|
||||||
|
|
@ -55,16 +67,12 @@ export function LoggingScreen({
|
||||||
}: LoggingScreenProps) {
|
}: LoggingScreenProps) {
|
||||||
const [filterText, setFilterText] = useState("");
|
const [filterText, setFilterText] = useState("");
|
||||||
const [visibleLevels, setVisibleLevels] =
|
const [visibleLevels, setVisibleLevels] =
|
||||||
useState<Record<string, boolean>>(ALL_LEVELS_VISIBLE);
|
useState<Record<LoggingLevel, boolean>>(ALL_LEVELS_VISIBLE);
|
||||||
|
|
||||||
function handleToggleLevel(level: string, visible: boolean) {
|
function handleToggleLevel(level: LoggingLevel, visible: boolean) {
|
||||||
setVisibleLevels((prev) => ({ ...prev, [level]: visible }));
|
setVisibleLevels((prev) => ({ ...prev, [level]: visible }));
|
||||||
}
|
}
|
||||||
|
|
||||||
const NO_LEVELS_VISIBLE: Record<string, boolean> = Object.fromEntries(
|
|
||||||
Object.keys(ALL_LEVELS_VISIBLE).map((k) => [k, false]),
|
|
||||||
);
|
|
||||||
|
|
||||||
function handleToggleAllLevels() {
|
function handleToggleAllLevels() {
|
||||||
const allSelected = Object.values(visibleLevels).every(Boolean);
|
const allSelected = Object.values(visibleLevels).every(Boolean);
|
||||||
setVisibleLevels(allSelected ? NO_LEVELS_VISIBLE : ALL_LEVELS_VISIBLE);
|
setVisibleLevels(allSelected ? NO_LEVELS_VISIBLE : ALL_LEVELS_VISIBLE);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue