Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions dashboards/src/components/GridLayout/GridItemContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,6 @@ export function GridItemContent(props: GridItemContentProps): ReactElement {

const { data: plugin } = usePlugin('Panel', panelDefinition.spec.plugin.kind);

const queryDefinitions = queries ?? [];
const definitions = queryDefinitions.map((query) => {
return {
kind: query.spec.plugin.kind,
spec: query.spec.plugin.spec,
};
});

const pluginQueryOptions =
typeof plugin?.queryOptions === 'function'
? plugin?.queryOptions(panelDefinition.spec.plugin.spec)
Expand All @@ -125,7 +117,7 @@ export function GridItemContent(props: GridItemContentProps): ReactElement {
}}
>
<DataQueriesProvider
definitions={definitions}
definitions={queries ?? []}
options={{ suggestedStepMs, ...pluginQueryOptions }}
queryOptions={{ enabled: shouldQuery }}
>
Expand All @@ -142,7 +134,7 @@ export function GridItemContent(props: GridItemContentProps): ReactElement {
</DataQueriesProvider>
<QueryViewerDialog
open={openQueryViewer}
queryDefinitions={queryDefinitions}
queryDefinitions={queries ?? []}
onClose={() => setOpenQueryViewer(false)}
/>
</Box>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,30 +51,15 @@ export function PanelQueriesSharedControls({
[panelDefinition.spec.plugin.spec, pluginPreview]
);

const [previewDefinition, setPreviewDefinition] = useState(
() =>
panelDefinition.spec.queries?.map((query) => {
return {
kind: query.spec.plugin.kind,
spec: query.spec.plugin.spec,
};
}) ?? []
);
const [previewDefinition, setPreviewDefinition] = useState<QueryDefinition[]>(panelDefinition.spec.queries ?? []);

const handleOnQueriesChange = useCallback(
(queries: QueryDefinition[]) => {
onQueriesChange(queries);

// If the number of queries has changed, force preview definition update to remove results of deleted queries.
if (queries.length !== previewDefinition.length) {
setPreviewDefinition(
queries.map((query) => {
return {
kind: query.spec.plugin.kind,
spec: query.spec.plugin.spec,
};
})
);
setPreviewDefinition(queries);
}
},
[onQueriesChange, previewDefinition.length]
Expand All @@ -83,10 +68,7 @@ export function PanelQueriesSharedControls({
const handleRunQuery = useCallback((index: number, newDef: QueryDefinition) => {
setPreviewDefinition((prev) => {
const newDefinitions = [...prev];
newDefinitions[index] = {
kind: newDef.spec.plugin.kind,
spec: newDef.spec.plugin.spec,
};
newDefinitions[index] = newDef;
return newDefinitions;
});
}, []);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,28 @@

import { produce } from 'immer';
import { QueryDefinition, QueryPluginType } from '@perses-dev/spec';
import { Stack, IconButton, Typography, BoxProps, Box, CircularProgress } from '@mui/material';
import {
Stack,
IconButton,
Typography,
BoxProps,
Box,
CircularProgress,
TextField,
InputAdornment,
} from '@mui/material';
import DeleteIcon from 'mdi-material-ui/DeleteOutline';
import ChevronDown from 'mdi-material-ui/ChevronDown';
import ChevronRight from 'mdi-material-ui/ChevronRight';
import { forwardRef, ReactElement } from 'react';
import { forwardRef, ReactElement, useState } from 'react';
Comment thread
Gladorme marked this conversation as resolved.
import AlertIcon from 'mdi-material-ui/Alert';
import { InfoTooltip } from '@perses-dev/components';
import PencilIcon from 'mdi-material-ui/Pencil';
import CheckIcon from 'mdi-material-ui/Check';
import CloseIcon from 'mdi-material-ui/Close';
import { QueryData } from '../../runtime';
import { PluginEditor, PluginEditorProps, PluginEditorRef } from '../PluginEditor';
import { defaultQueryName } from './utils';

/**
* Properties for {@link QueryEditorContainer}
Expand Down Expand Up @@ -66,6 +79,25 @@ export const QueryEditorContainer = forwardRef<PluginEditorRef, QueryEditorConta
onQueryRun,
onCollapseExpand,
} = props;

const [isEditingName, setIsEditingName] = useState(false);
const [name, setName] = useState(query.spec.name ?? defaultQueryName(index));

function handleNameChange(): void {
setIsEditingName(false);
onChange(
index,
produce(query, (draft) => {
draft.spec.name = name;
})
);
}

function handleNameCancel(): void {
setName(query.spec.name ?? defaultQueryName(index));
setIsEditingName(false);
}
Comment on lines +83 to +99

return (
<Stack key={index} spacing={1}>
<Stack
Expand All @@ -75,13 +107,52 @@ export const QueryEditorContainer = forwardRef<PluginEditorRef, QueryEditorConta
borderBottom={1}
borderColor={(theme) => theme.palette.divider}
>
<Stack direction="row">
<IconButton size="small" onClick={() => onCollapseExpand(index)}>
<Stack direction="row" gap={1} sx={{ width: '100%' }}>
<IconButton
size="small"
sx={{ width: 'fit-content', height: 'fit-content' }}
onClick={() => onCollapseExpand(index)}
>
{isCollapsed ? <ChevronRight /> : <ChevronDown />}
</IconButton>
<Typography variant="overline" component="h4">
Query #{index + 1}
</Typography>
<Stack
direction="row"
gap={1}
alignItems="center"
alignContent="center"
sx={{
width: '100%',
'&:hover button': {
visibility: 'visible',
},
}}
>
{isEditingName ? (
<TextField
size="small"
variant="outlined"
value={name}
onChange={(e) => setName(e.target.value)}
fullWidth={true}
InputProps={{
endAdornment: (
<InputAdornment position="end">
<IconButton size="small" aria-label="cancel edit" onClick={handleNameCancel} edge="end">
<CloseIcon />
</IconButton>
<IconButton size="small" aria-label="save query name" onClick={handleNameChange} edge="end">
<CheckIcon />
</IconButton>
</InputAdornment>
),
}}
/>
) : (
<Typography variant="overline" component="h4">
{name}
</Typography>
Comment on lines +131 to +153
)}
</Stack>
</Stack>
<Stack direction="row" alignItems="center">
{queryResult?.isFetching && <CircularProgress aria-label="loading" size="1.125rem" />}
Expand Down Expand Up @@ -117,11 +188,18 @@ export const QueryEditorContainer = forwardRef<PluginEditorRef, QueryEditorConta
</Stack>
</InfoTooltip>
)}
{onDelete && (
<IconButton aria-label="delete query" size="small" onClick={() => onDelete && onDelete(index)}>
<DeleteIcon />
</IconButton>
)}
<Stack>
{!isEditingName && (
<IconButton aria-label="edit query name" size="small" onClick={() => setIsEditingName(true)}>
<PencilIcon fontSize="small" />
</IconButton>
)}
{onDelete && (
<IconButton aria-label="delete query" size="small" onClick={() => onDelete && onDelete(index)}>
<DeleteIcon />
</IconButton>
)}
</Stack>
</Stack>
</Stack>
{!isCollapsed && (
Expand Down
1 change: 1 addition & 0 deletions plugin-system/src/components/MultiQueryEditor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,4 @@
// limitations under the License.

export * from './MultiQueryEditor';
export * from './utils';
30 changes: 30 additions & 0 deletions plugin-system/src/components/MultiQueryEditor/utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright The Perses Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { QueryDefinition } from '@perses-dev/spec';

export function defaultQueryName(index: number): string {
return `Query #${index + 1}`;
}

export function getQueryName(definitions: QueryDefinition[], query: QueryDefinition): string {
if (query.spec.name) {
return query.spec.name;
}
const index = definitions.findIndex((definition) => definition === query);
return defaultQueryName(index);
}
Comment thread
Gladorme marked this conversation as resolved.

export function generateQueryNames(definitions: QueryDefinition[]): string[] {
return definitions.map((queryDef: QueryDefinition, index: number) => queryDef.spec.name ?? defaultQueryName(index));
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('PanelSpecEditor', () => {
const renderComponent = (props: Omit<PanelSpecEditorProps, 'control'>): void => {
const DataQueriesProviderMock = (childProps: { children: ReactElement }): ReactElement => {
const ctx = {
queryDefinitions: [],
queryResults: [],
refetchAll: (): void => {},
isFetching: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { ErrorAlert, JSONEditor, LinksEditor } from '@perses-dev/components';
import { PanelDefinition, PanelEditorValues, QueryDefinition, UnknownSpec } from '@perses-dev/spec';
import { Control, Controller } from 'react-hook-form';
import { forwardRef, ReactElement } from 'react';
import { QueryCountProvider, useDataQueriesContext, usePlugin } from '../../runtime';
import { useDataQueriesContext, usePlugin } from '../../runtime';
import { PanelPlugin } from '../../model';
import { OptionsEditorTabsProps, OptionsEditorTabs } from '../OptionsEditorTabs';
import { MultiQueryEditor } from '../MultiQueryEditor';
Expand Down Expand Up @@ -131,11 +131,7 @@ export const PanelSpecEditor = forwardRef<PluginEditorRef, PanelSpecEditorProps>
),
});

return (
<QueryCountProvider queryCount={(panelDefinition.spec.queries ?? []).length}>
<OptionsEditorTabs key={tabs.length} tabs={tabs} />
</QueryCountProvider>
);
return <OptionsEditorTabs key={tabs.length} tabs={tabs} />;
});

PanelSpecEditor.displayName = 'PanelSpecEditor';
Loading
Loading