-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(LabelsView): Include/exclude panel actions #210
Merged
Merged
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
999fe8d
feat(LabelsView): Include/exclude panel actions
grafakus a514516
Merge branch 'main' into feat/label-views-include-exclude-actions
grafakus a7ca54f
Merge branch 'main' into feat/label-views-include-exclude-actions
grafakus a648a2d
Merge branch 'main' into feat/label-views-include-exclude-actions
grafakus 0bef275
feat: WiP Include/Exclude actions
grafakus 346e131
feat: WiP include/exclude logic
grafakus a9095e8
test(*): Add missing unit tests
grafakus b87e371
chore: ...
grafakus edb6176
chore: Remove comments
grafakus d647ee5
fix(EndToEnd): Update tests
grafakus 96b978d
chore: Remove unneeded export
grafakus 535cb14
Merge branch 'main' into feat/label-views-include-exclude-actions
grafakus aef42a2
feat: Add tracking
grafakus f41b1ec
feat(IncludeExcludeAction): Compute correct status for = and != opera…
grafakus 2fadbbf
fix: Fix/update logic
grafakus 5a47591
refactor(IncludeExclude): Split responsibilities
grafakus ff5b07e
refactor(FilterButtons): Split resp
grafakus f6aa996
feat: Simplify logic
grafakus 281e9ee
feat: Simplified logic
grafakus File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Binary file modified
BIN
-4.26 KB
(96%)
...s/Favorites-view-Panel-actions-Labels-action-with-group-by-1-chromium-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file removed
BIN
-79.7 KB
...fter-selecting-a-label-Panel-actions-Add-to-filters-action-1-chromium-linux.png
Binary file not shown.
Binary file modified
BIN
+162 Bytes
(100%)
...r-Selects-a-label-and-displays-the-breakdown-in-a-new-grid-1-chromium-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified
BIN
+162 Bytes
(100%)
....spec.ts-snapshots/Labels-view-Panel-actions-Select-action-1-chromium-linux.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
...yLabels/components/SceneLabelValuesGrid/infrastructure/buildLabelValuesGridQueryRunner.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import { SceneQueryRunner } from '@grafana/scenes'; | ||
|
||
import { PYROSCOPE_DATA_SOURCE } from '../../../../../../../infrastructure/pyroscope-data-sources'; | ||
grafakus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
export function buildLabelValuesGridQueryRunner({ label }: { label: string }) { | ||
const selector = 'service_name="$serviceName"'; | ||
|
||
return new SceneQueryRunner({ | ||
datasource: PYROSCOPE_DATA_SOURCE, | ||
queries: [ | ||
{ | ||
refId: `$profileMetricId-${selector}-${label}`, | ||
queryType: 'metrics', | ||
profileTypeId: '$profileMetricId', | ||
labelSelector: `{${selector}}`, | ||
groupBy: [label], | ||
}, | ||
], | ||
}); | ||
} |
75 changes: 75 additions & 0 deletions
75
...omponents/SceneGroupByLabels/domain/actions/IncludeExcludeAction/IncludeExcludeAction.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import { AdHocVariableFilter } from '@grafana/data'; | ||
import { SceneComponentProps, sceneGraph, SceneObjectBase, SceneObjectState } from '@grafana/scenes'; | ||
import { isRegexOperator } from '@shared/components/QueryBuilder/domain/helpers/isRegexOperator'; | ||
import { reportInteraction } from '@shared/domain/reportInteraction'; | ||
import React, { useMemo } from 'react'; | ||
|
||
import { FiltersVariable } from '../../../../../../../domain/variables/FiltersVariable/FiltersVariable'; | ||
import { GridItemData } from '../../../../../../SceneByVariableRepeaterGrid/types/GridItemData'; | ||
import { EventClearLabelFromFilters } from '../../events/EventClearLabelFromFilters'; | ||
import { EventExcludeLabelFromFilters } from '../../events/EventExcludeLabelFromFilters'; | ||
import { EventIncludeLabelInFilters } from '../../events/EventIncludeLabelInFilters'; | ||
import { FilterButtons } from './ui/FilterButtons'; | ||
|
||
export interface IncludeExcludeActionState extends SceneObjectState { | ||
item: GridItemData; | ||
} | ||
|
||
export class IncludeExcludeAction extends SceneObjectBase<IncludeExcludeActionState> { | ||
constructor({ item }: IncludeExcludeActionState) { | ||
super({ item }); | ||
} | ||
|
||
getStatus(filters: AdHocVariableFilter[]) { | ||
const { key, value } = this.state.item.queryRunnerParams.filters![0]; | ||
|
||
const found = filters.find((f) => f.key === key); | ||
if (!found) { | ||
return 'clear'; | ||
} | ||
|
||
if (isRegexOperator(found.operator) && found.value.split('|').includes(value)) { | ||
return found.operator === '=~' ? 'included' : 'excluded'; | ||
} | ||
|
||
// found.operator is '=' or '!=' | ||
if (found.value === value) { | ||
return found.operator === '=' ? 'included' : 'excluded'; | ||
} | ||
|
||
return 'clear'; | ||
} | ||
|
||
onInclude = () => { | ||
reportInteraction('g_pyroscope_app_include_action_clicked'); | ||
|
||
this.publishEvent(new EventIncludeLabelInFilters({ item: this.state.item }), true); | ||
}; | ||
|
||
onExclude = () => { | ||
reportInteraction('g_pyroscope_app_exclude_action_clicked'); | ||
|
||
this.publishEvent(new EventExcludeLabelFromFilters({ item: this.state.item }), true); | ||
}; | ||
|
||
onClear = () => { | ||
this.publishEvent(new EventClearLabelFromFilters({ item: this.state.item }), true); | ||
}; | ||
|
||
public static Component = ({ model }: SceneComponentProps<IncludeExcludeAction>) => { | ||
const { item } = model.useState(); | ||
|
||
const { filters } = (sceneGraph.findByKeyAndType(model, 'filters', FiltersVariable) as FiltersVariable).useState(); | ||
const status = useMemo(() => model.getStatus(filters), [filters, model]); | ||
grafakus marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
return ( | ||
<FilterButtons | ||
label={item.value} | ||
status={status} | ||
onInclude={model.onInclude} | ||
onExclude={model.onExclude} | ||
onClear={model.onClear} | ||
/> | ||
); | ||
}; | ||
} |
96 changes: 96 additions & 0 deletions
96
...ls/components/SceneGroupByLabels/domain/actions/IncludeExcludeAction/ui/FilterButtons.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import { css, cx } from '@emotion/css'; | ||
import { GrafanaTheme2 } from '@grafana/data'; | ||
import { Button, useStyles2 } from '@grafana/ui'; | ||
import React, { memo } from 'react'; | ||
|
||
type FilterButtonsProps = { | ||
label: string; | ||
status: 'included' | 'excluded' | 'clear'; | ||
onInclude: () => void; | ||
onExclude: () => void; | ||
onClear: () => void; | ||
}; | ||
|
||
function getStatus({ status, label, onInclude, onExclude, onClear }: FilterButtonsProps) { | ||
const isIncludeSelected = status === 'included'; | ||
const includeTooltip = !isIncludeSelected ? `Include "${label}" in the filters` : `Clear "${label}" from the filters`; | ||
|
||
const isExcludeSelected = status === 'excluded'; | ||
const excludeTooltip = !isExcludeSelected ? `Exclude "${label}" in the filters` : `Clear "${label}" from the filters`; | ||
|
||
return { | ||
include: { | ||
isSelected: isIncludeSelected, | ||
tooltip: includeTooltip, | ||
onClick: isIncludeSelected ? onClear : onInclude, | ||
}, | ||
exclude: { | ||
isSelected: isExcludeSelected, | ||
tooltip: excludeTooltip, | ||
onClick: isExcludeSelected ? onClear : onExclude, | ||
}, | ||
}; | ||
} | ||
|
||
// Kindly borrowed and adapted from https://github.com/grafana/explore-logs/blob/main/src/Components/FilterButton.tsx :) | ||
const FilterButtonsComponent = (props: FilterButtonsProps) => { | ||
const styles = useStyles2(getStyles); | ||
|
||
const { include, exclude } = getStatus(props); | ||
|
||
return ( | ||
<div className={styles.container}> | ||
<Button | ||
size="sm" | ||
fill="outline" | ||
variant={include.isSelected ? 'primary' : 'secondary'} | ||
aria-selected={include.isSelected} | ||
className={cx(styles.includeButton, include.isSelected && 'selected')} | ||
onClick={include.onClick} | ||
tooltip={include.tooltip} | ||
tooltipPlacement="top" | ||
data-testid="filter-button-include" | ||
> | ||
Include | ||
</Button> | ||
<Button | ||
size="sm" | ||
fill="outline" | ||
variant={exclude.isSelected ? 'primary' : 'secondary'} | ||
aria-selected={exclude.isSelected} | ||
className={cx(styles.excludeButton, exclude.isSelected && 'selected')} | ||
onClick={exclude.onClick} | ||
tooltip={exclude.tooltip} | ||
tooltipPlacement="top" | ||
data-testid="filter-button-exclude" | ||
> | ||
Exclude | ||
</Button> | ||
</div> | ||
); | ||
}; | ||
|
||
export const FilterButtons = memo(FilterButtonsComponent); | ||
|
||
const getStyles = (theme: GrafanaTheme2) => { | ||
return { | ||
container: css` | ||
display: flex; | ||
justify-content: center; | ||
`, | ||
includeButton: css` | ||
border-radius: ${theme.shape.radius.default} 0 0 ${theme.shape.radius.default}; | ||
|
||
&:not(.selected) { | ||
border-right: none; | ||
} | ||
`, | ||
excludeButton: css` | ||
border-radius: 0 ${theme.shape.radius.default} ${theme.shape.radius.default} 0; | ||
|
||
&:not(.selected) { | ||
border-left: none; | ||
} | ||
`, | ||
}; | ||
}; |
11 changes: 11 additions & 0 deletions
11
...eServiceLabels/components/SceneGroupByLabels/domain/events/EventClearLabelFromFilters.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { BusEventWithPayload } from '@grafana/data'; | ||
|
||
import { GridItemData } from '../../../../../SceneByVariableRepeaterGrid/types/GridItemData'; | ||
|
||
export interface EventClearLabelFromFiltersPayload { | ||
item: GridItemData; | ||
} | ||
|
||
export class EventClearLabelFromFilters extends BusEventWithPayload<EventClearLabelFromFiltersPayload> { | ||
public static type = 'clear-label-from-filters'; | ||
} |
11 changes: 11 additions & 0 deletions
11
...erviceLabels/components/SceneGroupByLabels/domain/events/EventExcludeLabelFromFilters.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { BusEventWithPayload } from '@grafana/data'; | ||
|
||
import { GridItemData } from '../../../../../SceneByVariableRepeaterGrid/types/GridItemData'; | ||
|
||
export interface EventExcludeLabelFromFiltersPayload { | ||
item: GridItemData; | ||
} | ||
|
||
export class EventExcludeLabelFromFilters extends BusEventWithPayload<EventExcludeLabelFromFiltersPayload> { | ||
public static type = 'exclude-label-from-filters'; | ||
} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exchanged for unit tests below