Logs Panel: Sync visual options in panel editor (#111163)

* Logs panel: sync visual options in panel editor

* LogListContext: sync uniqueLabels

* Tranlations

* Prettier

* PrettifyJSON before syntax highlighting

* Update LogListContext.tsx

* LogListContext: fix prettify json option callback

* LogListControls: fix third state for wrapping

* Update test

* chore: fix label capitalization
This commit is contained in:
Matias Chomicki 2025-09-17 12:13:13 +02:00 committed by GitHub
parent 8c284cbcba
commit a044f567a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 51 additions and 39 deletions

View File

@ -75,6 +75,7 @@ export interface Props {
permalinkedLogId?: string; permalinkedLogId?: string;
pinLineButtonTooltipTitle?: PopoverContent; pinLineButtonTooltipTitle?: PopoverContent;
pinnedLogs?: string[]; pinnedLogs?: string[];
prettifyJSON?: boolean;
setDisplayedFields?: (displayedFields: string[]) => void; setDisplayedFields?: (displayedFields: string[]) => void;
showControls: boolean; showControls: boolean;
showTime: boolean; showTime: boolean;
@ -88,7 +89,7 @@ export interface Props {
export type LogListFontSize = 'default' | 'small'; export type LogListFontSize = 'default' | 'small';
export type LogListControlOptions = keyof LogListState | 'wrapLogMessage' | 'prettifyJSON'; export type LogListControlOptions = keyof LogListState | 'wrapLogMessage' | 'prettifyLogMessage';
type LogListComponentProps = Omit< type LogListComponentProps = Omit<
Props, Props,
@ -143,6 +144,7 @@ export const LogList = ({
permalinkedLogId, permalinkedLogId,
pinLineButtonTooltipTitle, pinLineButtonTooltipTitle,
pinnedLogs, pinnedLogs,
prettifyJSON = logOptionsStorageKey ? store.getBool(`${logOptionsStorageKey}.prettifyLogMessage`, true) : true,
setDisplayedFields, setDisplayedFields,
showControls, showControls,
showTime, showTime,
@ -186,6 +188,7 @@ export const LogList = ({
permalinkedLogId={permalinkedLogId} permalinkedLogId={permalinkedLogId}
pinLineButtonTooltipTitle={pinLineButtonTooltipTitle} pinLineButtonTooltipTitle={pinLineButtonTooltipTitle}
pinnedLogs={pinnedLogs} pinnedLogs={pinnedLogs}
prettifyJSON={prettifyJSON}
setDisplayedFields={setDisplayedFields} setDisplayedFields={setDisplayedFields}
showControls={showControls} showControls={showControls}
showTime={showTime} showTime={showTime}

View File

@ -151,8 +151,6 @@ export type LogListState = Pick<
| 'timestampResolution' | 'timestampResolution'
>; >;
export type LogListOption = keyof LogListState | 'wrapLogMessage' | 'prettifyJSON';
export interface Props { export interface Props {
app: CoreApp; app: CoreApp;
children?: ReactNode; children?: ReactNode;
@ -233,9 +231,7 @@ export const LogListContextProvider = ({
permalinkedLogId, permalinkedLogId,
pinLineButtonTooltipTitle, pinLineButtonTooltipTitle,
pinnedLogs, pinnedLogs,
prettifyJSON: prettifyJSONProp = logOptionsStorageKey prettifyJSON: prettifyJSONProp,
? store.getBool(`${logOptionsStorageKey}.prettifyLogMessage`, true)
: true,
setDisplayedFields, setDisplayedFields,
showControls, showControls,
showTime, showTime,
@ -280,8 +276,10 @@ export const LogListContextProvider = ({
fontSize, fontSize,
forceEscape: logListState.forceEscape, forceEscape: logListState.forceEscape,
showTime, showTime,
showUniqueLabels,
syntaxHighlighting, syntaxHighlighting,
wrapLogMessage, wrapLogMessage,
prettifyJSON,
detailsWidth, detailsWidth,
detailsMode, detailsMode,
withDisplayedFields: displayedFields.length > 0, withDisplayedFields: displayedFields.length > 0,
@ -312,24 +310,14 @@ export const LogListContextProvider = ({
...logListState, ...logListState,
dedupStrategy, dedupStrategy,
showTime, showTime,
showUniqueLabels,
sortOrder, sortOrder,
syntaxHighlighting, syntaxHighlighting,
wrapLogMessage,
}; };
if (!shallowCompare(logListState, newState)) { if (!shallowCompare(logListState, newState)) {
setLogListState(newState); setLogListState(newState);
} }
}, [ }, [app, dedupStrategy, logListState, showControls, showTime, showUniqueLabels, sortOrder, syntaxHighlighting]);
app,
dedupStrategy,
logListState,
pinnedLogs,
showControls,
showTime,
sortOrder,
syntaxHighlighting,
wrapLogMessage,
]);
// Sync filter levels // Sync filter levels
useEffect(() => { useEffect(() => {
@ -344,6 +332,11 @@ export const LogListContextProvider = ({
}); });
}, [filterLevels]); }, [filterLevels]);
// Sync details mode
useEffect(() => {
setDetailsMode(detailsModeProp);
}, [detailsModeProp]);
// Sync font size // Sync font size
useEffect(() => { useEffect(() => {
setLogListState((logListState) => ({ ...logListState, fontSize })); setLogListState((logListState) => ({ ...logListState, fontSize }));
@ -389,6 +382,18 @@ export const LogListContextProvider = ({
return () => observer.disconnect(); return () => observer.disconnect();
}, [containerElement, detailsMode, logOptionsStorageKey, showControls]); }, [containerElement, detailsMode, logOptionsStorageKey, showControls]);
// Sync prettifyJSON
useEffect(() => {
if (prettifyJSONProp !== undefined) {
setPrettifyJSONState(prettifyJSONProp);
}
}, [prettifyJSONProp]);
// Sync wrapLogMessage
useEffect(() => {
setWrapLogMessageState(wrapLogMessageProp);
}, [wrapLogMessageProp]);
// Sync timestamp resolution // Sync timestamp resolution
useEffect(() => { useEffect(() => {
setLogListState((state) => ({ setLogListState((state) => ({
@ -485,7 +490,7 @@ export const LogListContextProvider = ({
if (logOptionsStorageKey) { if (logOptionsStorageKey) {
store.set(`${logOptionsStorageKey}.prettifyLogMessage`, prettifyJSON); store.set(`${logOptionsStorageKey}.prettifyLogMessage`, prettifyJSON);
} }
onLogOptionsChange?.('prettifyJSON', prettifyJSON); onLogOptionsChange?.('prettifyLogMessage', prettifyJSON);
}, },
[logOptionsStorageKey, onLogOptionsChange] [logOptionsStorageKey, onLogOptionsChange]
); );

View File

@ -303,19 +303,19 @@ describe('LogListControls', () => {
expect(onLogOptionsChange).toHaveBeenCalledTimes(2); expect(onLogOptionsChange).toHaveBeenCalledTimes(2);
expect(onLogOptionsChange).toHaveBeenCalledWith('wrapLogMessage', true); expect(onLogOptionsChange).toHaveBeenCalledWith('wrapLogMessage', true);
expect(onLogOptionsChange).toHaveBeenCalledWith('prettifyJSON', false); expect(onLogOptionsChange).toHaveBeenCalledWith('prettifyLogMessage', false);
await userEvent.click(screen.getByLabelText(WRAP_LINES_LABEL_COPY)); await userEvent.click(screen.getByLabelText(WRAP_LINES_LABEL_COPY));
await userEvent.click(screen.getByText(WRAP_JSON_TOOLTIP_COPY)); await userEvent.click(screen.getByText(WRAP_JSON_TOOLTIP_COPY));
expect(onLogOptionsChange).toHaveBeenCalledTimes(4); expect(onLogOptionsChange).toHaveBeenCalledTimes(4);
expect(onLogOptionsChange).toHaveBeenCalledWith('prettifyJSON', true); expect(onLogOptionsChange).toHaveBeenCalledWith('prettifyLogMessage', true);
await userEvent.click(screen.getByLabelText(WRAP_JSON_LABEL_COPY)); await userEvent.click(screen.getByLabelText(WRAP_JSON_LABEL_COPY));
await userEvent.click(screen.getByText(WRAP_DISABLE_LABEL_COPY)); await userEvent.click(screen.getByText(WRAP_DISABLE_LABEL_COPY));
expect(onLogOptionsChange).toHaveBeenCalledWith('wrapLogMessage', false); expect(onLogOptionsChange).toHaveBeenCalledWith('wrapLogMessage', false);
expect(onLogOptionsChange).toHaveBeenCalledWith('prettifyJSON', false); expect(onLogOptionsChange).toHaveBeenCalledWith('prettifyLogMessage', false);
expect(onLogOptionsChange).toHaveBeenCalledTimes(6); expect(onLogOptionsChange).toHaveBeenCalledTimes(6);

View File

@ -735,7 +735,7 @@ const WrapLogMessageButton = ({ expanded }: LogSelectOptionProps) => {
tooltip={tooltip} tooltip={tooltip}
label={wrapStateText} label={wrapStateText}
buttonAriaLabel={tooltip} buttonAriaLabel={tooltip}
customTagText={'+'} customTagText={prettifyJSON ? '+' : ''}
/> />
); );
}; };

View File

@ -69,7 +69,7 @@ export const LogListControlsSelectOption = React.forwardRef<SVGElement, SelectPr
className: iconButtonClassName, className: iconButtonClassName,
name: iconButtonName, name: iconButtonName,
dropdown, dropdown,
isActive: isActive, isActive,
customTagText, customTagText,
buttonAriaLabel, buttonAriaLabel,
...iconButtonProps ...iconButtonProps

View File

@ -606,6 +606,7 @@ export const LogsPanel = ({
onOpenContext={onOpenContext} onOpenContext={onOpenContext}
onPermalinkClick={showPermaLink() ? onPermalinkClick : undefined} onPermalinkClick={showPermaLink() ? onPermalinkClick : undefined}
permalinkedLogId={getLogsPanelState()?.logs?.id ?? undefined} permalinkedLogId={getLogsPanelState()?.logs?.id ?? undefined}
prettifyJSON={prettifyLogMessage}
setDisplayedFields={setDisplayedFieldsFn} setDisplayedFields={setDisplayedFieldsFn}
showControls={Boolean(showControls)} showControls={Boolean(showControls)}
showTime={showTime} showTime={showTime}

View File

@ -60,17 +60,8 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
defaultValue: false, defaultValue: false,
}); });
if (config.featureToggles.newLogsPanel) { // In the old panel this is an independent option, in the new panel is linked to wrapLogMessage
builder.addBooleanSwitch({ if (!config.featureToggles.newLogsPanel || context.options?.wrapLogMessage) {
path: 'syntaxHighlighting',
name: t('logs.name-enable-syntax-highlighting', 'Enable syntax highlighting'),
category,
description: t(
'logs.description-enable-syntax-highlighting',
'Use a predefined syntax coloring grammar to highlight relevant parts of the log lines'
),
});
} else {
builder.addBooleanSwitch({ builder.addBooleanSwitch({
path: 'prettifyLogMessage', path: 'prettifyLogMessage',
name: t('logs.name-prettify-json', 'Prettify JSON'), name: t('logs.name-prettify-json', 'Prettify JSON'),
@ -80,6 +71,18 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
}); });
} }
if (config.featureToggles.newLogsPanel) {
builder.addBooleanSwitch({
path: 'syntaxHighlighting',
name: t('logs.name-enable-logs-highlighting', 'Enable logs highlighting'),
category,
description: t(
'logs.description-enable-logs-highlighting',
'Use a predefined coloring scheme to highlight relevant parts of the log lines'
),
});
}
builder.addBooleanSwitch({ builder.addBooleanSwitch({
path: 'enableLogDetails', path: 'enableLogDetails',
name: t('logs.name-enable-log-details', 'Enable log details'), name: t('logs.name-enable-log-details', 'Enable log details'),
@ -91,7 +94,7 @@ export const plugin = new PanelPlugin<Options>(LogsPanel)
if (config.featureToggles.newLogsPanel && context.options?.enableLogDetails) { if (config.featureToggles.newLogsPanel && context.options?.enableLogDetails) {
builder.addRadio({ builder.addRadio({
path: 'detailsMode', path: 'detailsMode',
name: t('logs.name-details-mode', 'Log Details panel mode'), name: t('logs.name-details-mode', 'Log details panel mode'),
category, category,
description: '', description: '',
settings: { settings: {

View File

@ -9439,7 +9439,7 @@
"label-signature": "Signature" "label-signature": "Signature"
}, },
"description-enable-infinite-scrolling": "Experimental. Request more results by scrolling to the bottom of the logs list.", "description-enable-infinite-scrolling": "Experimental. Request more results by scrolling to the bottom of the logs list.",
"description-enable-syntax-highlighting": "Use a predefined syntax coloring grammar to highlight relevant parts of the log lines", "description-enable-logs-highlighting": "Use a predefined coloring scheme to highlight relevant parts of the log lines",
"description-show-controls": "Display controls to jump to the last or first log line, and filters by log level", "description-show-controls": "Display controls to jump to the last or first log line, and filters by log level",
"fields": { "fields": {
"type": { "type": {
@ -9711,14 +9711,14 @@
}, },
"name-common-labels": "Common labels", "name-common-labels": "Common labels",
"name-deduplication": "Deduplication", "name-deduplication": "Deduplication",
"name-details-mode": "Log Details panel mode", "name-details-mode": "Log details panel mode",
"name-details-options": { "name-details-options": {
"label-inline": "Inline", "label-inline": "Inline",
"label-sidebar": "Sidebar" "label-sidebar": "Sidebar"
}, },
"name-enable-infinite-scrolling": "Enable infinite scrolling", "name-enable-infinite-scrolling": "Enable infinite scrolling",
"name-enable-log-details": "Enable log details", "name-enable-log-details": "Enable log details",
"name-enable-syntax-highlighting": "Enable syntax highlighting", "name-enable-logs-highlighting": "Enable logs highlighting",
"name-font-size": "Font size", "name-font-size": "Font size",
"name-order": "Order", "name-order": "Order",
"name-prettify-json": "Prettify JSON", "name-prettify-json": "Prettify JSON",