mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Prometheus: Query builder UX tweaks and feedback link (#47655)
* Prometheus: Query builder UX tweaks and feedback link * Remove . * Fixed link * added option to hide feedback links * feedback link setting name change * move config check * fixed ts issue
This commit is contained in:
parent
782ec05d8c
commit
057ff5bcf5
@ -230,6 +230,9 @@ application_insights_connection_string =
|
||||
# Optional. Specifies an Application Insights endpoint URL where the endpoint string is wrapped in backticks ``.
|
||||
application_insights_endpoint_url =
|
||||
|
||||
# Controls if the UI contains any links to user feedback forms
|
||||
feedback_links_enabled = true
|
||||
|
||||
#################################### Security ############################
|
||||
[security]
|
||||
# disable creation of admin user on first start of grafana
|
||||
|
@ -230,6 +230,9 @@
|
||||
# Rudderstack Config url, optional, used by Rudderstack SDK to fetch source config
|
||||
;rudderstack_config_url =
|
||||
|
||||
# Controls if the UI contains any links to user feedback forms
|
||||
;feedback_links_enabled = true
|
||||
|
||||
#################################### Security ####################################
|
||||
[security]
|
||||
# disable creation of admin user on first start of grafana
|
||||
|
@ -509,6 +509,10 @@ If you want to track Grafana usage via Azure Application Insights, then specify
|
||||
|
||||
<hr />
|
||||
|
||||
### enable_feedback_links
|
||||
|
||||
If set to false will remove all feedback links from the UI. Defaults to true.
|
||||
|
||||
## [security]
|
||||
|
||||
### disable_initial_admin_creation
|
||||
|
@ -180,4 +180,5 @@ export interface GrafanaConfig {
|
||||
geomapDisableCustomBaseLayer?: boolean;
|
||||
unifiedAlertingEnabled: boolean;
|
||||
angularSupportEnabled: boolean;
|
||||
feedbackLinksEnabled: boolean;
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ export class GrafanaBootConfig implements GrafanaConfig {
|
||||
externalUserMngLinkName = '';
|
||||
externalUserMngInfo = '';
|
||||
allowOrgCreate = false;
|
||||
feedbackLinksEnabled = true;
|
||||
disableLoginForm = false;
|
||||
defaultDatasource = ''; // UID
|
||||
alertingEnabled = false;
|
||||
|
@ -113,6 +113,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i
|
||||
"rudderstackDataPlaneUrl": setting.RudderstackDataPlaneUrl,
|
||||
"rudderstackSdkUrl": setting.RudderstackSdkUrl,
|
||||
"rudderstackConfigUrl": setting.RudderstackConfigUrl,
|
||||
"feedbackLinksEnabled": hs.Cfg.FeedbackLinksEnabled,
|
||||
"applicationInsightsConnectionString": hs.Cfg.ApplicationInsightsConnectionString,
|
||||
"applicationInsightsEndpointUrl": hs.Cfg.ApplicationInsightsEndpointUrl,
|
||||
"disableLoginForm": setting.DisableLoginForm,
|
||||
|
@ -393,6 +393,7 @@ type Cfg struct {
|
||||
ReportingEnabled bool
|
||||
ApplicationInsightsConnectionString string
|
||||
ApplicationInsightsEndpointUrl string
|
||||
FeedbackLinksEnabled bool
|
||||
|
||||
// LDAP
|
||||
LDAPEnabled bool
|
||||
@ -938,13 +939,17 @@ func (cfg *Cfg) Load(args CommandLineArgs) error {
|
||||
RudderstackDataPlaneUrl = analytics.Key("rudderstack_data_plane_url").String()
|
||||
RudderstackSdkUrl = analytics.Key("rudderstack_sdk_url").String()
|
||||
RudderstackConfigUrl = analytics.Key("rudderstack_config_url").String()
|
||||
|
||||
cfg.ReportingEnabled = analytics.Key("reporting_enabled").MustBool(true)
|
||||
cfg.ReportingDistributor = analytics.Key("reporting_distributor").MustString("grafana-labs")
|
||||
|
||||
if len(cfg.ReportingDistributor) >= 100 {
|
||||
cfg.ReportingDistributor = cfg.ReportingDistributor[:100]
|
||||
}
|
||||
|
||||
cfg.ApplicationInsightsConnectionString = analytics.Key("application_insights_connection_string").String()
|
||||
cfg.ApplicationInsightsEndpointUrl = analytics.Key("application_insights_endpoint_url").String()
|
||||
cfg.FeedbackLinksEnabled = analytics.Key("feedback_links_enabled").MustBool(true)
|
||||
|
||||
if err := readAlertingSettings(iniFile); err != nil {
|
||||
return err
|
||||
|
@ -54,7 +54,7 @@ export function PromQueryBuilderContainer(props: Props) {
|
||||
onRunQuery={onRunQuery}
|
||||
data={data}
|
||||
/>
|
||||
{query.editorPreview && <QueryPreview query={query.expr} />}
|
||||
{query.rawQuery && <QueryPreview query={query.expr} />}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -90,24 +90,24 @@ describe('PromQueryEditorSelector', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('Can enable preview', async () => {
|
||||
it('Can enable raw query', async () => {
|
||||
const { onChange } = renderWithMode(QueryEditorMode.Builder);
|
||||
expect(screen.queryByLabelText('selector')).not.toBeInTheDocument();
|
||||
|
||||
screen.getByLabelText('Preview').click();
|
||||
screen.getByLabelText('Raw query').click();
|
||||
|
||||
expect(onChange).toBeCalledWith({
|
||||
refId: 'A',
|
||||
expr: defaultQuery.expr,
|
||||
range: true,
|
||||
editorMode: QueryEditorMode.Builder,
|
||||
editorPreview: true,
|
||||
rawQuery: true,
|
||||
});
|
||||
});
|
||||
|
||||
it('Should show preview', async () => {
|
||||
it('Should show raw query', async () => {
|
||||
renderWithProps({
|
||||
editorPreview: true,
|
||||
rawQuery: true,
|
||||
editorMode: QueryEditorMode.Builder,
|
||||
expr: 'my_metric',
|
||||
});
|
||||
|
@ -14,6 +14,7 @@ import { PromQueryBuilderContainer } from './PromQueryBuilderContainer';
|
||||
import { PromQueryBuilderOptions } from './PromQueryBuilderOptions';
|
||||
import { changeEditorMode, getQueryWithDefaults } from '../state';
|
||||
import { PromQuery } from '../../types';
|
||||
import { FeedbackLink } from '../shared/FeedbackLink';
|
||||
|
||||
export const PromQueryEditorSelector = React.memo<PromQueryEditorProps>((props) => {
|
||||
const { onChange, onRunQuery, data } = props;
|
||||
@ -44,7 +45,7 @@ export const PromQueryEditorSelector = React.memo<PromQueryEditorProps>((props)
|
||||
|
||||
const onQueryPreviewChange = (event: SyntheticEvent<HTMLInputElement>) => {
|
||||
const isEnabled = event.currentTarget.checked;
|
||||
onChange({ ...query, editorPreview: isEnabled });
|
||||
onChange({ ...query, rawQuery: isEnabled });
|
||||
onRunQuery();
|
||||
};
|
||||
|
||||
@ -67,16 +68,6 @@ export const PromQueryEditorSelector = React.memo<PromQueryEditorProps>((props)
|
||||
onDismiss={() => setParseModalOpen(false)}
|
||||
/>
|
||||
<EditorHeader>
|
||||
<FlexItem grow={1} />
|
||||
<Button
|
||||
variant={dataIsStale ? 'primary' : 'secondary'}
|
||||
size="sm"
|
||||
onClick={onRunQuery}
|
||||
icon={data?.state === LoadingState.Loading ? 'fa fa-spinner' : undefined}
|
||||
disabled={data?.state === LoadingState.Loading}
|
||||
>
|
||||
Run query
|
||||
</Button>
|
||||
{editorMode === QueryEditorMode.Builder && (
|
||||
<>
|
||||
<InlineSelect
|
||||
@ -95,14 +86,22 @@ export const PromQueryEditorSelector = React.memo<PromQueryEditorProps>((props)
|
||||
}}
|
||||
options={promQueryModeller.getQueryPatterns().map((x) => ({ label: x.name, value: x }))}
|
||||
/>
|
||||
<QueryHeaderSwitch label="Raw query" value={query.rawQuery} onChange={onQueryPreviewChange} />
|
||||
</>
|
||||
)}
|
||||
<QueryHeaderSwitch
|
||||
label="Preview"
|
||||
value={query.editorPreview}
|
||||
onChange={onQueryPreviewChange}
|
||||
disabled={editorMode !== QueryEditorMode.Builder}
|
||||
/>
|
||||
{editorMode === QueryEditorMode.Builder && (
|
||||
<FeedbackLink feedbackUrl="https://github.com/grafana/grafana/discussions/47693" />
|
||||
)}
|
||||
<FlexItem grow={1} />
|
||||
<Button
|
||||
variant={dataIsStale ? 'primary' : 'secondary'}
|
||||
size="sm"
|
||||
onClick={onRunQuery}
|
||||
icon={data?.state === LoadingState.Loading ? 'fa fa-spinner' : undefined}
|
||||
disabled={data?.state === LoadingState.Loading}
|
||||
>
|
||||
Run query
|
||||
</Button>
|
||||
<QueryEditorModeToggle mode={editorMode} onChange={onEditorModeChange} />
|
||||
</EditorHeader>
|
||||
<Space v={0.5} />
|
||||
|
@ -18,7 +18,7 @@ export function QueryPreview({ query }: Props) {
|
||||
return (
|
||||
<EditorRow>
|
||||
<EditorFieldGroup>
|
||||
<EditorField label="Preview">
|
||||
<EditorField label="Raw query">
|
||||
<div
|
||||
className={cx(styles.editorField, 'prism-syntax-highlight')}
|
||||
aria-label="selector"
|
||||
|
@ -0,0 +1,44 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { Stack } from '@grafana/experimental';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Icon, useStyles2 } from '@grafana/ui';
|
||||
import React from 'react';
|
||||
|
||||
export interface Props {
|
||||
feedbackUrl?: string;
|
||||
}
|
||||
|
||||
export function FeedbackLink({ feedbackUrl }: Props) {
|
||||
const styles = useStyles2(getStyles);
|
||||
|
||||
if (!config.feedbackLinksEnabled) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Stack gap={1}>
|
||||
<a
|
||||
href={feedbackUrl}
|
||||
className={styles.link}
|
||||
title="This query builder is new, please let us know how we can improve it"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener"
|
||||
>
|
||||
<Icon name="comment-alt-message" /> Give feedback
|
||||
</a>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
function getStyles(theme: GrafanaTheme2) {
|
||||
return {
|
||||
link: css({
|
||||
color: theme.colors.text.secondary,
|
||||
fontSize: theme.typography.bodySmall.fontSize,
|
||||
':hover': {
|
||||
color: theme.colors.text.link,
|
||||
},
|
||||
}),
|
||||
};
|
||||
}
|
@ -19,8 +19,8 @@ export interface PromQuery extends DataQuery {
|
||||
showingTable?: boolean;
|
||||
/** Code, Builder or Explain */
|
||||
editorMode?: QueryEditorMode;
|
||||
/** Controls if the query preview is shown */
|
||||
editorPreview?: boolean;
|
||||
/** Controls if the raw query text is shown */
|
||||
rawQuery?: boolean;
|
||||
}
|
||||
|
||||
export interface PromOptions extends DataSourceJsonData {
|
||||
|
Loading…
Reference in New Issue
Block a user