@grafana/scenes 6.50.0--canary.1312.20235582466.0 → 6.50.0--canary.1312.20242044820.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersComboboxRenderer.js +2 -21
- package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersComboboxRenderer.js.map +1 -1
- package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersRecommendations.js +174 -0
- package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersRecommendations.js.map +1 -0
- package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersVariable.js +16 -83
- package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersVariable.js.map +1 -1
- package/dist/esm/packages/scenes/src/variables/adhoc/controller/AdHocFiltersVariableController.js +1 -2
- package/dist/esm/packages/scenes/src/variables/adhoc/controller/AdHocFiltersVariableController.js.map +1 -1
- package/dist/esm/packages/scenes/src/variables/groupby/GroupByRecommendations.js +192 -0
- package/dist/esm/packages/scenes/src/variables/groupby/GroupByRecommendations.js.map +1 -0
- package/dist/esm/packages/scenes/src/variables/groupby/GroupByVariable.js +10 -114
- package/dist/esm/packages/scenes/src/variables/groupby/GroupByVariable.js.map +1 -1
- package/dist/index.d.ts +93 -21
- package/dist/index.js +612 -467
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3614,6 +3614,186 @@ function getInteractionTracker(sceneObject) {
|
|
|
3614
3614
|
return void 0;
|
|
3615
3615
|
}
|
|
3616
3616
|
|
|
3617
|
+
function DrilldownRecommendations({ recentDrilldowns, recommendedDrilldowns }) {
|
|
3618
|
+
const styles = ui.useStyles2(getStyles$k);
|
|
3619
|
+
const [isPopoverVisible, setPopoverVisible] = React.useState(false);
|
|
3620
|
+
const ref = React.useRef(null);
|
|
3621
|
+
const openPopover = () => {
|
|
3622
|
+
setPopoverVisible(true);
|
|
3623
|
+
};
|
|
3624
|
+
const onClickAction = (action) => {
|
|
3625
|
+
action();
|
|
3626
|
+
setPopoverVisible(false);
|
|
3627
|
+
};
|
|
3628
|
+
const content = /* @__PURE__ */ React__default.default.createElement(ui.ClickOutsideWrapper, { onClick: () => setPopoverVisible(false), useCapture: true }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.menuContainer, onClick: (ev) => ev.stopPropagation() }, /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column" }, /* @__PURE__ */ React__default.default.createElement(ui.Text, { weight: "bold", variant: "bodySmall", color: "secondary" }, /* @__PURE__ */ React__default.default.createElement(i18n.Trans, { i18nKey: "grafana-scenes.components.drilldown-recommendations.recent" }, "Recent")), recentDrilldowns && recentDrilldowns.length > 0 ? recentDrilldowns.map((drilldown) => /* @__PURE__ */ React__default.default.createElement(
|
|
3629
|
+
"div",
|
|
3630
|
+
{
|
|
3631
|
+
key: drilldown.label,
|
|
3632
|
+
className: css.cx(styles.combinedFilterPill),
|
|
3633
|
+
onClick: () => onClickAction(drilldown.onClick)
|
|
3634
|
+
},
|
|
3635
|
+
drilldown.label
|
|
3636
|
+
)) : /* @__PURE__ */ React__default.default.createElement("div", { className: styles.emptyMessage }, /* @__PURE__ */ React__default.default.createElement(i18n.Trans, { i18nKey: "grafana-scenes.components.drilldown-recommendations.recent-empty" }, "No recent values")), /* @__PURE__ */ React__default.default.createElement(ui.Text, { weight: "bold", variant: "bodySmall", color: "secondary" }, /* @__PURE__ */ React__default.default.createElement(i18n.Trans, { i18nKey: "grafana-scenes.components.drilldown-recommendations.recommended" }, "Recommended")), recommendedDrilldowns && recommendedDrilldowns.length > 0 ? recommendedDrilldowns.map((drilldown) => /* @__PURE__ */ React__default.default.createElement(
|
|
3637
|
+
"div",
|
|
3638
|
+
{
|
|
3639
|
+
key: drilldown.label,
|
|
3640
|
+
className: css.cx(styles.combinedFilterPill),
|
|
3641
|
+
onClick: () => onClickAction(drilldown.onClick)
|
|
3642
|
+
},
|
|
3643
|
+
drilldown.label
|
|
3644
|
+
)) : /* @__PURE__ */ React__default.default.createElement("div", { className: styles.emptyMessage }, /* @__PURE__ */ React__default.default.createElement(i18n.Trans, { i18nKey: "grafana-scenes.components.drilldown-recommendations.recommended-empty" }, "No recommended values")))));
|
|
3645
|
+
return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(
|
|
3646
|
+
ui.IconButton,
|
|
3647
|
+
{
|
|
3648
|
+
name: "plus",
|
|
3649
|
+
tooltip: i18n.t("grafana-scenes.components.drilldown-recommendations.tooltip", "Show recommendations"),
|
|
3650
|
+
ref,
|
|
3651
|
+
className: css.cx(isPopoverVisible && styles.iconActive),
|
|
3652
|
+
onClick: (ev) => {
|
|
3653
|
+
openPopover();
|
|
3654
|
+
ev.stopPropagation();
|
|
3655
|
+
}
|
|
3656
|
+
}
|
|
3657
|
+
), isPopoverVisible && ref.current && /* @__PURE__ */ React__default.default.createElement(
|
|
3658
|
+
ui.Popover,
|
|
3659
|
+
{
|
|
3660
|
+
content,
|
|
3661
|
+
onKeyDown: (event) => {
|
|
3662
|
+
if (event.key === " ") {
|
|
3663
|
+
event.stopPropagation();
|
|
3664
|
+
}
|
|
3665
|
+
},
|
|
3666
|
+
placement: "bottom-start",
|
|
3667
|
+
referenceElement: ref.current,
|
|
3668
|
+
show: true
|
|
3669
|
+
}
|
|
3670
|
+
));
|
|
3671
|
+
}
|
|
3672
|
+
const getStyles$k = (theme) => ({
|
|
3673
|
+
menuContainer: css.css({
|
|
3674
|
+
display: "flex",
|
|
3675
|
+
flexDirection: "column",
|
|
3676
|
+
background: theme.colors.background.elevated,
|
|
3677
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
3678
|
+
borderRadius: theme.shape.radius.default,
|
|
3679
|
+
boxShadow: theme.shadows.z3,
|
|
3680
|
+
padding: theme.spacing(2)
|
|
3681
|
+
}),
|
|
3682
|
+
combinedFilterPill: css.css({
|
|
3683
|
+
alignItems: "center",
|
|
3684
|
+
background: theme.colors.action.selected,
|
|
3685
|
+
borderRadius: theme.shape.radius.default,
|
|
3686
|
+
border: `1px solid ${theme.colors.border.weak}`,
|
|
3687
|
+
padding: theme.spacing(0.2, 1),
|
|
3688
|
+
color: theme.colors.text.primary,
|
|
3689
|
+
overflow: "hidden",
|
|
3690
|
+
whiteSpace: "nowrap",
|
|
3691
|
+
minHeight: theme.spacing(2.75),
|
|
3692
|
+
...theme.typography.bodySmall,
|
|
3693
|
+
fontWeight: theme.typography.fontWeightBold,
|
|
3694
|
+
cursor: "pointer",
|
|
3695
|
+
"&:hover": {
|
|
3696
|
+
background: theme.colors.action.hover
|
|
3697
|
+
}
|
|
3698
|
+
}),
|
|
3699
|
+
iconActive: css.css({
|
|
3700
|
+
"&:before": {
|
|
3701
|
+
backgroundColor: theme.colors.action.hover,
|
|
3702
|
+
opacity: 1
|
|
3703
|
+
}
|
|
3704
|
+
}),
|
|
3705
|
+
emptyMessage: css.css({
|
|
3706
|
+
padding: theme.spacing(0.5, 0),
|
|
3707
|
+
color: theme.colors.text.secondary,
|
|
3708
|
+
...theme.typography.bodySmall
|
|
3709
|
+
})
|
|
3710
|
+
});
|
|
3711
|
+
|
|
3712
|
+
class ScopesVariable extends SceneObjectBase {
|
|
3713
|
+
constructor(state) {
|
|
3714
|
+
super({
|
|
3715
|
+
skipUrlSync: true,
|
|
3716
|
+
loading: true,
|
|
3717
|
+
scopes: [],
|
|
3718
|
+
...state,
|
|
3719
|
+
type: "system",
|
|
3720
|
+
name: SCOPES_VARIABLE_NAME,
|
|
3721
|
+
hide: schema.VariableHide.hideVariable
|
|
3722
|
+
});
|
|
3723
|
+
this._renderBeforeActivation = true;
|
|
3724
|
+
// Special options that enables variables to be hidden but still render to access react contexts
|
|
3725
|
+
this.UNSAFE_renderAsHidden = true;
|
|
3726
|
+
}
|
|
3727
|
+
/**
|
|
3728
|
+
* Temporary simple implementation to stringify the scopes.
|
|
3729
|
+
*/
|
|
3730
|
+
getValue() {
|
|
3731
|
+
var _a;
|
|
3732
|
+
const scopes = (_a = this.state.scopes) != null ? _a : [];
|
|
3733
|
+
return new ScopesVariableFormatter(scopes.map((scope) => scope.metadata.name));
|
|
3734
|
+
}
|
|
3735
|
+
getScopes() {
|
|
3736
|
+
return this.state.scopes;
|
|
3737
|
+
}
|
|
3738
|
+
/**
|
|
3739
|
+
* This method is used to keep the context up to date with the scopes context received from React
|
|
3740
|
+
* 1) Subscribes to ScopesContext state changes and synchronizes it with the variable state
|
|
3741
|
+
* 2) Handles enable / disabling of scopes based on variable enable option.
|
|
3742
|
+
*/
|
|
3743
|
+
setContext(context) {
|
|
3744
|
+
if (!context) {
|
|
3745
|
+
return;
|
|
3746
|
+
}
|
|
3747
|
+
this._context = context;
|
|
3748
|
+
const oldState = context.state;
|
|
3749
|
+
if (this.state.enable != null) {
|
|
3750
|
+
context.setEnabled(this.state.enable);
|
|
3751
|
+
}
|
|
3752
|
+
const sub = context.stateObservable.subscribe((state) => {
|
|
3753
|
+
this.updateStateFromContext(state);
|
|
3754
|
+
});
|
|
3755
|
+
return () => {
|
|
3756
|
+
sub.unsubscribe();
|
|
3757
|
+
if (this.state.enable != null) {
|
|
3758
|
+
context.setEnabled(oldState.enabled);
|
|
3759
|
+
}
|
|
3760
|
+
};
|
|
3761
|
+
}
|
|
3762
|
+
updateStateFromContext(state) {
|
|
3763
|
+
const loading = state.value.length === 0 ? false : state.loading;
|
|
3764
|
+
const oldScopes = this.state.scopes.map((scope) => scope.metadata.name);
|
|
3765
|
+
const newScopes = state.value.map((scope) => scope.metadata.name);
|
|
3766
|
+
const scopesHaveChanged = !lodash.isEqual(oldScopes, newScopes);
|
|
3767
|
+
if (!loading && (scopesHaveChanged || newScopes.length === 0)) {
|
|
3768
|
+
const queryController = getQueryController(this);
|
|
3769
|
+
queryController == null ? void 0 : queryController.startProfile(SCOPES_CHANGED_INTERACTION);
|
|
3770
|
+
this.setState({ scopes: state.value, loading });
|
|
3771
|
+
this.publishEvent(new SceneVariableValueChangedEvent(this), true);
|
|
3772
|
+
} else {
|
|
3773
|
+
this.setState({ loading });
|
|
3774
|
+
}
|
|
3775
|
+
}
|
|
3776
|
+
}
|
|
3777
|
+
ScopesVariable.Component = ScopesVariableRenderer;
|
|
3778
|
+
function ScopesVariableRenderer({ model }) {
|
|
3779
|
+
const context = React.useContext(runtime.ScopesContext);
|
|
3780
|
+
React.useEffect(() => {
|
|
3781
|
+
return model.setContext(context);
|
|
3782
|
+
}, [context, model]);
|
|
3783
|
+
return null;
|
|
3784
|
+
}
|
|
3785
|
+
class ScopesVariableFormatter {
|
|
3786
|
+
constructor(_value) {
|
|
3787
|
+
this._value = _value;
|
|
3788
|
+
}
|
|
3789
|
+
formatter(formatNameOrFn) {
|
|
3790
|
+
if (formatNameOrFn === schema.VariableFormatID.QueryParam) {
|
|
3791
|
+
return this._value.map((scope) => `scope=${encodeURIComponent(scope)}`).join("&");
|
|
3792
|
+
}
|
|
3793
|
+
return this._value.join(", ");
|
|
3794
|
+
}
|
|
3795
|
+
}
|
|
3796
|
+
|
|
3617
3797
|
let originalGetAdhocFilters = void 0;
|
|
3618
3798
|
const allActiveFilterSets = /* @__PURE__ */ new Set();
|
|
3619
3799
|
function patchGetAdhocFilters(filterVar) {
|
|
@@ -3673,7 +3853,7 @@ function LoadingIndicator(props) {
|
|
|
3673
3853
|
}
|
|
3674
3854
|
|
|
3675
3855
|
function ControlsLabel(props) {
|
|
3676
|
-
const styles = ui.useStyles2(getStyles$
|
|
3856
|
+
const styles = ui.useStyles2(getStyles$j);
|
|
3677
3857
|
const theme = ui.useTheme2();
|
|
3678
3858
|
const isVertical = props.layout === "vertical";
|
|
3679
3859
|
const loadingIndicator = Boolean(props.isLoading) ? /* @__PURE__ */ React__default.default.createElement(
|
|
@@ -3720,7 +3900,7 @@ function ControlsLabel(props) {
|
|
|
3720
3900
|
}
|
|
3721
3901
|
return labelElement;
|
|
3722
3902
|
}
|
|
3723
|
-
const getStyles$
|
|
3903
|
+
const getStyles$j = (theme) => ({
|
|
3724
3904
|
horizontalLabel: css.css({
|
|
3725
3905
|
background: theme.isDark ? theme.colors.background.primary : theme.colors.background.secondary,
|
|
3726
3906
|
display: `flex`,
|
|
@@ -3773,7 +3953,7 @@ function keyLabelToOption(key, label) {
|
|
|
3773
3953
|
const filterNoOp$1 = () => true;
|
|
3774
3954
|
function AdHocFilterRenderer({ filter, model }) {
|
|
3775
3955
|
var _a, _b, _c, _d, _e;
|
|
3776
|
-
const styles = ui.useStyles2(getStyles$
|
|
3956
|
+
const styles = ui.useStyles2(getStyles$i);
|
|
3777
3957
|
const [keys, setKeys] = React.useState([]);
|
|
3778
3958
|
const [values, setValues] = React.useState([]);
|
|
3779
3959
|
const [isKeysLoading, setIsKeysLoading] = React.useState(false);
|
|
@@ -4000,7 +4180,7 @@ function AdHocFilterRenderer({ filter, model }) {
|
|
|
4000
4180
|
}
|
|
4001
4181
|
));
|
|
4002
4182
|
}
|
|
4003
|
-
const getStyles$
|
|
4183
|
+
const getStyles$i = (theme) => ({
|
|
4004
4184
|
field: css.css({
|
|
4005
4185
|
marginBottom: 0
|
|
4006
4186
|
}),
|
|
@@ -4073,7 +4253,7 @@ const getStyles$j = (theme) => ({
|
|
|
4073
4253
|
|
|
4074
4254
|
function AdHocFilterBuilder({ model, addFilterButtonText }) {
|
|
4075
4255
|
const { _wip } = model.useState();
|
|
4076
|
-
const styles = ui.useStyles2(getStyles$
|
|
4256
|
+
const styles = ui.useStyles2(getStyles$h);
|
|
4077
4257
|
if (!_wip) {
|
|
4078
4258
|
return /* @__PURE__ */ React__default.default.createElement(
|
|
4079
4259
|
ui.Button,
|
|
@@ -4091,7 +4271,7 @@ function AdHocFilterBuilder({ model, addFilterButtonText }) {
|
|
|
4091
4271
|
}
|
|
4092
4272
|
return /* @__PURE__ */ React__default.default.createElement(AdHocFilterRenderer, { filter: _wip, model });
|
|
4093
4273
|
}
|
|
4094
|
-
const getStyles$
|
|
4274
|
+
const getStyles$h = (theme) => ({
|
|
4095
4275
|
addButton: css.css({
|
|
4096
4276
|
"&:first-child": {
|
|
4097
4277
|
borderBottomLeftRadius: 0,
|
|
@@ -4216,7 +4396,7 @@ function isFilter(filter) {
|
|
|
4216
4396
|
|
|
4217
4397
|
const DropdownItem = React.forwardRef(
|
|
4218
4398
|
function DropdownItem2({ children, active, addGroupBottomBorder, isMultiValueEdit, checked, ...rest }, ref) {
|
|
4219
|
-
const styles = ui.useStyles2(getStyles$
|
|
4399
|
+
const styles = ui.useStyles2(getStyles$g);
|
|
4220
4400
|
const id = React.useId();
|
|
4221
4401
|
return /* @__PURE__ */ React__default.default.createElement(
|
|
4222
4402
|
"div",
|
|
@@ -4232,7 +4412,7 @@ const DropdownItem = React.forwardRef(
|
|
|
4232
4412
|
);
|
|
4233
4413
|
}
|
|
4234
4414
|
);
|
|
4235
|
-
const getStyles$
|
|
4415
|
+
const getStyles$g = (theme) => ({
|
|
4236
4416
|
option: css.css({
|
|
4237
4417
|
label: "grafana-select-option",
|
|
4238
4418
|
top: 0,
|
|
@@ -4302,7 +4482,7 @@ const MultiValueApplyButton = ({
|
|
|
4302
4482
|
maxOptionWidth,
|
|
4303
4483
|
menuHeight
|
|
4304
4484
|
}) => {
|
|
4305
|
-
const styles = ui.useStyles2(getStyles$
|
|
4485
|
+
const styles = ui.useStyles2(getStyles$g);
|
|
4306
4486
|
const floatingElementRect = floatingElement == null ? void 0 : floatingElement.getBoundingClientRect();
|
|
4307
4487
|
return /* @__PURE__ */ React__default.default.createElement(
|
|
4308
4488
|
"div",
|
|
@@ -4523,7 +4703,7 @@ const MultiValuePill = ({
|
|
|
4523
4703
|
handleEditMultiValuePill
|
|
4524
4704
|
}) => {
|
|
4525
4705
|
var _a, _b;
|
|
4526
|
-
const styles = ui.useStyles2(getStyles$
|
|
4706
|
+
const styles = ui.useStyles2(getStyles$f);
|
|
4527
4707
|
const editMultiValuePill = React.useCallback(
|
|
4528
4708
|
(e) => {
|
|
4529
4709
|
e.stopPropagation();
|
|
@@ -4587,7 +4767,7 @@ const MultiValuePill = ({
|
|
|
4587
4767
|
)
|
|
4588
4768
|
);
|
|
4589
4769
|
};
|
|
4590
|
-
const getStyles$
|
|
4770
|
+
const getStyles$f = (theme) => ({
|
|
4591
4771
|
basePill: css.css({
|
|
4592
4772
|
display: "flex",
|
|
4593
4773
|
alignItems: "center",
|
|
@@ -4633,7 +4813,7 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({
|
|
|
4633
4813
|
const [activeIndex, setActiveIndex] = React.useState(null);
|
|
4634
4814
|
const [filterInputType, setInputType] = React.useState(!isAlwaysWip ? "value" : "key");
|
|
4635
4815
|
const [preventFiltering, setPreventFiltering] = React.useState(!isAlwaysWip && filterInputType === "value");
|
|
4636
|
-
const styles = ui.useStyles2(getStyles$
|
|
4816
|
+
const styles = ui.useStyles2(getStyles$e);
|
|
4637
4817
|
const [filterMultiValues, setFilterMultiValues] = React.useState([]);
|
|
4638
4818
|
const [_, setForceRefresh] = React.useState({});
|
|
4639
4819
|
const { allowCustomValue = true, onAddCustomValue, filters, inputPlaceholder } = controller.useState();
|
|
@@ -5239,7 +5419,7 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({
|
|
|
5239
5419
|
}
|
|
5240
5420
|
) : null))));
|
|
5241
5421
|
});
|
|
5242
|
-
const getStyles$
|
|
5422
|
+
const getStyles$e = (theme) => ({
|
|
5243
5423
|
comboboxWrapper: css.css({
|
|
5244
5424
|
display: "flex",
|
|
5245
5425
|
flexWrap: "wrap"
|
|
@@ -5313,7 +5493,7 @@ const getStyles$f = (theme) => ({
|
|
|
5313
5493
|
const LABEL_MAX_VISIBLE_LENGTH = 20;
|
|
5314
5494
|
function AdHocFilterPill({ filter, controller, readOnly, focusOnWipInputRef }) {
|
|
5315
5495
|
var _a, _b, _c, _d;
|
|
5316
|
-
const styles = ui.useStyles2(getStyles$
|
|
5496
|
+
const styles = ui.useStyles2(getStyles$d);
|
|
5317
5497
|
const [viewMode, setViewMode] = React.useState(true);
|
|
5318
5498
|
const [shouldFocusOnPillWrapper, setShouldFocusOnPillWrapper] = React.useState(false);
|
|
5319
5499
|
const pillWrapperRef = React.useRef(null);
|
|
@@ -5491,7 +5671,7 @@ function AdHocFilterPill({ filter, controller, readOnly, focusOnWipInputRef }) {
|
|
|
5491
5671
|
}
|
|
5492
5672
|
);
|
|
5493
5673
|
}
|
|
5494
|
-
const getStyles$
|
|
5674
|
+
const getStyles$d = (theme) => ({
|
|
5495
5675
|
combinedFilterPill: css.css({
|
|
5496
5676
|
display: "flex",
|
|
5497
5677
|
alignItems: "center",
|
|
@@ -5573,134 +5753,21 @@ const AdHocFiltersAlwaysWipCombobox = React.forwardRef(function AdHocFiltersAlwa
|
|
|
5573
5753
|
return /* @__PURE__ */ React__default.default.createElement(AdHocCombobox, { controller, filter: wip, isAlwaysWip: true, ref: parentRef });
|
|
5574
5754
|
});
|
|
5575
5755
|
|
|
5576
|
-
function
|
|
5577
|
-
const
|
|
5578
|
-
const
|
|
5579
|
-
const
|
|
5580
|
-
|
|
5581
|
-
setPopoverVisible(true);
|
|
5582
|
-
};
|
|
5583
|
-
const onClickAction = (action) => {
|
|
5584
|
-
action();
|
|
5585
|
-
setPopoverVisible(false);
|
|
5586
|
-
};
|
|
5587
|
-
const content = /* @__PURE__ */ React__default.default.createElement(ui.ClickOutsideWrapper, { onClick: () => setPopoverVisible(false), useCapture: true }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.menuContainer, onClick: (ev) => ev.stopPropagation() }, /* @__PURE__ */ React__default.default.createElement(ui.Stack, { direction: "column" }, /* @__PURE__ */ React__default.default.createElement(ui.Text, { weight: "bold", variant: "bodySmall", color: "secondary" }, /* @__PURE__ */ React__default.default.createElement(i18n.Trans, { i18nKey: "grafana-scenes.components.drilldown-recommendations.recent" }, "Recent")), recentDrilldowns && recentDrilldowns.length > 0 ? recentDrilldowns.map((drilldown) => /* @__PURE__ */ React__default.default.createElement(
|
|
5588
|
-
"div",
|
|
5589
|
-
{
|
|
5590
|
-
key: drilldown.label,
|
|
5591
|
-
className: css.cx(styles.combinedFilterPill),
|
|
5592
|
-
onClick: () => onClickAction(drilldown.onClick)
|
|
5593
|
-
},
|
|
5594
|
-
drilldown.label
|
|
5595
|
-
)) : /* @__PURE__ */ React__default.default.createElement("div", { className: styles.emptyMessage }, /* @__PURE__ */ React__default.default.createElement(i18n.Trans, { i18nKey: "grafana-scenes.components.drilldown-recommendations.recent-empty" }, "No recent values")), /* @__PURE__ */ React__default.default.createElement(ui.Text, { weight: "bold", variant: "bodySmall", color: "secondary" }, /* @__PURE__ */ React__default.default.createElement(i18n.Trans, { i18nKey: "grafana-scenes.components.drilldown-recommendations.recommended" }, "Recommended")), recommendedDrilldowns && recommendedDrilldowns.length > 0 ? recommendedDrilldowns.map((drilldown) => /* @__PURE__ */ React__default.default.createElement(
|
|
5756
|
+
const AdHocFiltersComboboxRenderer = React.memo(function AdHocFiltersComboboxRenderer2({ controller }) {
|
|
5757
|
+
const { originFilters, filters, readOnly, valueRecommendations, drilldownRecommendationsEnabled } = controller.useState();
|
|
5758
|
+
const styles = ui.useStyles2(getStyles$c);
|
|
5759
|
+
const focusOnWipInputRef = React.useRef();
|
|
5760
|
+
return /* @__PURE__ */ React__default.default.createElement(
|
|
5596
5761
|
"div",
|
|
5597
5762
|
{
|
|
5598
|
-
|
|
5599
|
-
|
|
5600
|
-
|
|
5601
|
-
|
|
5602
|
-
drilldown.label
|
|
5603
|
-
)) : /* @__PURE__ */ React__default.default.createElement("div", { className: styles.emptyMessage }, /* @__PURE__ */ React__default.default.createElement(i18n.Trans, { i18nKey: "grafana-scenes.components.drilldown-recommendations.recommended-empty" }, "No recommended values")))));
|
|
5604
|
-
return /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, null, /* @__PURE__ */ React__default.default.createElement(
|
|
5605
|
-
ui.IconButton,
|
|
5606
|
-
{
|
|
5607
|
-
name: "plus",
|
|
5608
|
-
tooltip: i18n.t("grafana-scenes.components.drilldown-recommendations.tooltip", "Show recommendations"),
|
|
5609
|
-
ref,
|
|
5610
|
-
className: css.cx(isPopoverVisible && styles.iconActive),
|
|
5611
|
-
onClick: (ev) => {
|
|
5612
|
-
openPopover();
|
|
5613
|
-
ev.stopPropagation();
|
|
5614
|
-
}
|
|
5615
|
-
}
|
|
5616
|
-
), isPopoverVisible && ref.current && /* @__PURE__ */ React__default.default.createElement(
|
|
5617
|
-
ui.Popover,
|
|
5618
|
-
{
|
|
5619
|
-
content,
|
|
5620
|
-
onKeyDown: (event) => {
|
|
5621
|
-
if (event.key === " ") {
|
|
5622
|
-
event.stopPropagation();
|
|
5623
|
-
}
|
|
5624
|
-
},
|
|
5625
|
-
placement: "bottom-start",
|
|
5626
|
-
referenceElement: ref.current,
|
|
5627
|
-
show: true
|
|
5628
|
-
}
|
|
5629
|
-
));
|
|
5630
|
-
}
|
|
5631
|
-
const getStyles$d = (theme) => ({
|
|
5632
|
-
menuContainer: css.css({
|
|
5633
|
-
display: "flex",
|
|
5634
|
-
flexDirection: "column",
|
|
5635
|
-
background: theme.colors.background.elevated,
|
|
5636
|
-
border: `1px solid ${theme.colors.border.weak}`,
|
|
5637
|
-
borderRadius: theme.shape.radius.default,
|
|
5638
|
-
boxShadow: theme.shadows.z3,
|
|
5639
|
-
padding: theme.spacing(2)
|
|
5640
|
-
}),
|
|
5641
|
-
combinedFilterPill: css.css({
|
|
5642
|
-
alignItems: "center",
|
|
5643
|
-
background: theme.colors.action.selected,
|
|
5644
|
-
borderRadius: theme.shape.radius.default,
|
|
5645
|
-
border: `1px solid ${theme.colors.border.weak}`,
|
|
5646
|
-
padding: theme.spacing(0.2, 1),
|
|
5647
|
-
color: theme.colors.text.primary,
|
|
5648
|
-
overflow: "hidden",
|
|
5649
|
-
whiteSpace: "nowrap",
|
|
5650
|
-
minHeight: theme.spacing(2.75),
|
|
5651
|
-
...theme.typography.bodySmall,
|
|
5652
|
-
fontWeight: theme.typography.fontWeightBold,
|
|
5653
|
-
cursor: "pointer",
|
|
5654
|
-
"&:hover": {
|
|
5655
|
-
background: theme.colors.action.hover
|
|
5656
|
-
}
|
|
5657
|
-
}),
|
|
5658
|
-
iconActive: css.css({
|
|
5659
|
-
"&:before": {
|
|
5660
|
-
backgroundColor: theme.colors.action.hover,
|
|
5661
|
-
opacity: 1
|
|
5662
|
-
}
|
|
5663
|
-
}),
|
|
5664
|
-
emptyMessage: css.css({
|
|
5665
|
-
padding: theme.spacing(0.5, 0),
|
|
5666
|
-
color: theme.colors.text.secondary,
|
|
5667
|
-
...theme.typography.bodySmall
|
|
5668
|
-
})
|
|
5669
|
-
});
|
|
5670
|
-
|
|
5671
|
-
const AdHocFiltersComboboxRenderer = React.memo(function AdHocFiltersComboboxRenderer2({ controller }) {
|
|
5672
|
-
const { originFilters, filters, readOnly, recentFilters, recommendedFilters, drilldownRecommendationsEnabled } = controller.useState();
|
|
5673
|
-
const styles = ui.useStyles2(getStyles$c);
|
|
5674
|
-
let drilldownRecommendationComponent = null;
|
|
5675
|
-
if (drilldownRecommendationsEnabled) {
|
|
5676
|
-
const recentDrilldowns = recentFilters == null ? void 0 : recentFilters.map((filter) => ({
|
|
5677
|
-
label: `${filter.key} ${filter.operator} ${filter.value}`,
|
|
5678
|
-
onClick: () => {
|
|
5679
|
-
var _a;
|
|
5680
|
-
(_a = controller.updateFilters) == null ? void 0 : _a.call(controller, [...filters, filter]);
|
|
5681
|
-
}
|
|
5682
|
-
}));
|
|
5683
|
-
const recommendedDrilldowns = recommendedFilters == null ? void 0 : recommendedFilters.map((filter) => ({
|
|
5684
|
-
label: `${filter.key} ${filter.operator} ${filter.value}`,
|
|
5685
|
-
onClick: () => {
|
|
5686
|
-
var _a;
|
|
5687
|
-
(_a = controller.updateFilters) == null ? void 0 : _a.call(controller, [...filters, filter]);
|
|
5688
|
-
}
|
|
5689
|
-
}));
|
|
5690
|
-
drilldownRecommendationComponent = /* @__PURE__ */ React__default.default.createElement(DrilldownRecommendations, { recentDrilldowns, recommendedDrilldowns });
|
|
5691
|
-
}
|
|
5692
|
-
const focusOnWipInputRef = React.useRef();
|
|
5693
|
-
return /* @__PURE__ */ React__default.default.createElement(
|
|
5694
|
-
"div",
|
|
5695
|
-
{
|
|
5696
|
-
className: css.cx(styles.comboboxWrapper, { [styles.comboboxFocusOutline]: !readOnly }),
|
|
5697
|
-
onClick: () => {
|
|
5698
|
-
var _a;
|
|
5699
|
-
(_a = focusOnWipInputRef.current) == null ? void 0 : _a.call(focusOnWipInputRef);
|
|
5763
|
+
className: css.cx(styles.comboboxWrapper, { [styles.comboboxFocusOutline]: !readOnly }),
|
|
5764
|
+
onClick: () => {
|
|
5765
|
+
var _a;
|
|
5766
|
+
(_a = focusOnWipInputRef.current) == null ? void 0 : _a.call(focusOnWipInputRef);
|
|
5700
5767
|
}
|
|
5701
5768
|
},
|
|
5702
5769
|
/* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "filter", className: styles.filterIcon, size: "lg" }),
|
|
5703
|
-
|
|
5770
|
+
drilldownRecommendationsEnabled && valueRecommendations && /* @__PURE__ */ React__default.default.createElement(valueRecommendations.Component, { model: valueRecommendations }),
|
|
5704
5771
|
originFilters == null ? void 0 : originFilters.map(
|
|
5705
5772
|
(filter, index) => filter.origin ? /* @__PURE__ */ React__default.default.createElement(
|
|
5706
5773
|
AdHocFilterPill,
|
|
@@ -5858,8 +5925,7 @@ class AdHocFiltersVariableController {
|
|
|
5858
5925
|
supportsMultiValueOperators: state.supportsMultiValueOperators,
|
|
5859
5926
|
onAddCustomValue: state.onAddCustomValue,
|
|
5860
5927
|
wip: state._wip,
|
|
5861
|
-
|
|
5862
|
-
recommendedFilters: state._recommendedFilters,
|
|
5928
|
+
valueRecommendations: state._valueRecommendations,
|
|
5863
5929
|
drilldownRecommendationsEnabled: state.drilldownRecommendationsEnabled
|
|
5864
5930
|
};
|
|
5865
5931
|
}
|
|
@@ -5910,6 +5976,163 @@ class AdHocFiltersVariableController {
|
|
|
5910
5976
|
}
|
|
5911
5977
|
}
|
|
5912
5978
|
|
|
5979
|
+
class AdHocFiltersRecommendations extends SceneObjectBase {
|
|
5980
|
+
constructor(parent) {
|
|
5981
|
+
super({});
|
|
5982
|
+
this._scopedVars = { __sceneObject: wrapInSafeSerializableSceneObject(this) };
|
|
5983
|
+
this._activationHandler = () => {
|
|
5984
|
+
const json = data.store.get(this._getStorageKey());
|
|
5985
|
+
const storedFilters = json ? JSON.parse(json) : [];
|
|
5986
|
+
if (storedFilters.length > 0) {
|
|
5987
|
+
this._verifyRecentFiltersApplicability(storedFilters);
|
|
5988
|
+
} else {
|
|
5989
|
+
this.setState({ recentFilters: [] });
|
|
5990
|
+
}
|
|
5991
|
+
this._fetchRecommendedDrilldowns();
|
|
5992
|
+
const scopesVariable = sceneGraph.lookupVariable(SCOPES_VARIABLE_NAME, this);
|
|
5993
|
+
let scopesSubscription;
|
|
5994
|
+
if (scopesVariable instanceof ScopesVariable) {
|
|
5995
|
+
scopesSubscription = scopesVariable.subscribeToState((newState, prevState) => {
|
|
5996
|
+
if (newState.scopes !== prevState.scopes) {
|
|
5997
|
+
const json2 = data.store.get(this._getStorageKey());
|
|
5998
|
+
const storedFilters2 = json2 ? JSON.parse(json2) : [];
|
|
5999
|
+
if (storedFilters2.length > 0) {
|
|
6000
|
+
this._verifyRecentFiltersApplicability(storedFilters2);
|
|
6001
|
+
}
|
|
6002
|
+
}
|
|
6003
|
+
});
|
|
6004
|
+
}
|
|
6005
|
+
return () => {
|
|
6006
|
+
scopesSubscription == null ? void 0 : scopesSubscription.unsubscribe();
|
|
6007
|
+
};
|
|
6008
|
+
};
|
|
6009
|
+
this._parentVariable = parent;
|
|
6010
|
+
this.addActivationHandler(this._activationHandler);
|
|
6011
|
+
}
|
|
6012
|
+
/**
|
|
6013
|
+
* Get the parent variable
|
|
6014
|
+
*/
|
|
6015
|
+
get parent() {
|
|
6016
|
+
return this._parentVariable;
|
|
6017
|
+
}
|
|
6018
|
+
_getStorageKey() {
|
|
6019
|
+
var _a;
|
|
6020
|
+
return getRecentFiltersKey((_a = this._parentVariable.state.datasource) == null ? void 0 : _a.uid);
|
|
6021
|
+
}
|
|
6022
|
+
async _fetchRecommendedDrilldowns() {
|
|
6023
|
+
var _a;
|
|
6024
|
+
const parent = this._parentVariable;
|
|
6025
|
+
const ds = await getDataSource(parent.state.datasource, this._scopedVars);
|
|
6026
|
+
if (!ds || !ds.getRecommendedDrilldowns) {
|
|
6027
|
+
return;
|
|
6028
|
+
}
|
|
6029
|
+
const queries = parent.state.useQueriesAsFilterForOptions ? getQueriesForVariables(parent) : void 0;
|
|
6030
|
+
const timeRange = sceneGraph.getTimeRange(this).state.value;
|
|
6031
|
+
const scopes = sceneGraph.getScopes(this);
|
|
6032
|
+
const filters = [...(_a = parent.state.originFilters) != null ? _a : [], ...parent.state.filters];
|
|
6033
|
+
const enrichedRequest = getEnrichedDataRequest(this);
|
|
6034
|
+
const dashboardUid = enrichedRequest == null ? void 0 : enrichedRequest.dashboardUID;
|
|
6035
|
+
try {
|
|
6036
|
+
const recommendedDrilldowns = await ds.getRecommendedDrilldowns({
|
|
6037
|
+
timeRange,
|
|
6038
|
+
dashboardUid,
|
|
6039
|
+
queries: queries != null ? queries : [],
|
|
6040
|
+
filters,
|
|
6041
|
+
scopes,
|
|
6042
|
+
userId: runtime.config.bootData.user.id
|
|
6043
|
+
});
|
|
6044
|
+
if (recommendedDrilldowns == null ? void 0 : recommendedDrilldowns.filters) {
|
|
6045
|
+
this.setState({ recommendedFilters: recommendedDrilldowns.filters });
|
|
6046
|
+
}
|
|
6047
|
+
} catch (error) {
|
|
6048
|
+
console.error("Failed to fetch recommended drilldowns:", error);
|
|
6049
|
+
}
|
|
6050
|
+
}
|
|
6051
|
+
async _verifyRecentFiltersApplicability(storedFilters) {
|
|
6052
|
+
const parent = this._parentVariable;
|
|
6053
|
+
const queries = parent.state.useQueriesAsFilterForOptions ? getQueriesForVariables(parent) : void 0;
|
|
6054
|
+
const response = await this._getFiltersApplicabilityForQueries(storedFilters, queries != null ? queries : []);
|
|
6055
|
+
if (!response) {
|
|
6056
|
+
this.setState({ recentFilters: storedFilters.slice(-3) });
|
|
6057
|
+
return;
|
|
6058
|
+
}
|
|
6059
|
+
const applicabilityMap = /* @__PURE__ */ new Map();
|
|
6060
|
+
response.forEach((item) => {
|
|
6061
|
+
applicabilityMap.set(item.key, item.applicable !== false);
|
|
6062
|
+
});
|
|
6063
|
+
const applicableFilters = storedFilters.filter((f) => {
|
|
6064
|
+
const isApplicable = applicabilityMap.get(f.key);
|
|
6065
|
+
return isApplicable === void 0 || isApplicable === true;
|
|
6066
|
+
}).slice(-3);
|
|
6067
|
+
this.setState({ recentFilters: applicableFilters });
|
|
6068
|
+
}
|
|
6069
|
+
async _getFiltersApplicabilityForQueries(filters, queries) {
|
|
6070
|
+
const parent = this._parentVariable;
|
|
6071
|
+
const ds = await getDataSource(parent.state.datasource, this._scopedVars);
|
|
6072
|
+
if (!ds || !ds.getDrilldownsApplicability) {
|
|
6073
|
+
return;
|
|
6074
|
+
}
|
|
6075
|
+
const timeRange = sceneGraph.getTimeRange(this).state.value;
|
|
6076
|
+
return await ds.getDrilldownsApplicability({
|
|
6077
|
+
filters,
|
|
6078
|
+
queries,
|
|
6079
|
+
timeRange,
|
|
6080
|
+
scopes: sceneGraph.getScopes(this),
|
|
6081
|
+
...getEnrichedFiltersRequest(this)
|
|
6082
|
+
});
|
|
6083
|
+
}
|
|
6084
|
+
/**
|
|
6085
|
+
* Stores a recent filter in localStorage and updates state.
|
|
6086
|
+
* Should be called by the parent variable when a filter is added/updated.
|
|
6087
|
+
*/
|
|
6088
|
+
storeRecentFilter(filter) {
|
|
6089
|
+
const key = this._getStorageKey();
|
|
6090
|
+
const storedFilters = data.store.get(key);
|
|
6091
|
+
const allRecentFilters = storedFilters ? JSON.parse(storedFilters) : [];
|
|
6092
|
+
const updatedStoredFilters = [...allRecentFilters, filter].slice(-10);
|
|
6093
|
+
data.store.set(key, JSON.stringify(updatedStoredFilters));
|
|
6094
|
+
const parent = this._parentVariable;
|
|
6095
|
+
const existingFilter = parent.state.filters.find((f) => f.key === filter.key && !Boolean(f.nonApplicable));
|
|
6096
|
+
if (existingFilter && !Boolean(existingFilter.nonApplicable)) {
|
|
6097
|
+
this.setState({ recentFilters: updatedStoredFilters.slice(-3) });
|
|
6098
|
+
}
|
|
6099
|
+
}
|
|
6100
|
+
/**
|
|
6101
|
+
* Get the current filters from the parent variable
|
|
6102
|
+
*/
|
|
6103
|
+
getParentFilters() {
|
|
6104
|
+
return this._parentVariable.state.filters;
|
|
6105
|
+
}
|
|
6106
|
+
/**
|
|
6107
|
+
* Add a filter to the parent variable
|
|
6108
|
+
*/
|
|
6109
|
+
addFilterToParent(filter) {
|
|
6110
|
+
const parent = this._parentVariable;
|
|
6111
|
+
parent.updateFilters([...parent.state.filters, filter]);
|
|
6112
|
+
}
|
|
6113
|
+
}
|
|
6114
|
+
AdHocFiltersRecommendations.Component = AdHocFiltersRecommendationsRenderer;
|
|
6115
|
+
function AdHocFiltersRecommendationsRenderer({ model }) {
|
|
6116
|
+
const { recentFilters, recommendedFilters } = model.useState();
|
|
6117
|
+
const { filters } = model.parent.useState();
|
|
6118
|
+
const recentDrilldowns = recentFilters == null ? void 0 : recentFilters.map((filter) => ({
|
|
6119
|
+
label: `${filter.key} ${filter.operator} ${filter.value}`,
|
|
6120
|
+
onClick: () => {
|
|
6121
|
+
model.addFilterToParent(filter);
|
|
6122
|
+
}
|
|
6123
|
+
}));
|
|
6124
|
+
const recommendedDrilldowns = recommendedFilters == null ? void 0 : recommendedFilters.map((filter) => ({
|
|
6125
|
+
label: `${filter.key} ${filter.operator} ${filter.value}`,
|
|
6126
|
+
onClick: () => {
|
|
6127
|
+
const exists = filters.some((f) => f.key === filter.key && f.value === filter.value);
|
|
6128
|
+
if (!exists) {
|
|
6129
|
+
model.addFilterToParent(filter);
|
|
6130
|
+
}
|
|
6131
|
+
}
|
|
6132
|
+
}));
|
|
6133
|
+
return /* @__PURE__ */ React__default.default.createElement(DrilldownRecommendations, { recentDrilldowns, recommendedDrilldowns });
|
|
6134
|
+
}
|
|
6135
|
+
|
|
5913
6136
|
const ORIGIN_FILTERS_KEY = "originFilters";
|
|
5914
6137
|
const getRecentFiltersKey = (datasourceUid) => `grafana.filters.recent.${datasourceUid != null ? datasourceUid : "default"}`;
|
|
5915
6138
|
const OPERATORS = [
|
|
@@ -5985,21 +6208,15 @@ class AdHocFiltersVariable extends SceneObjectBase {
|
|
|
5985
6208
|
this._urlSync = new AdHocFiltersVariableUrlSyncHandler(this);
|
|
5986
6209
|
this._debouncedVerifyApplicability = lodash.debounce(this._verifyApplicability, 100);
|
|
5987
6210
|
this._activationHandler = () => {
|
|
5988
|
-
var _a;
|
|
5989
6211
|
this._debouncedVerifyApplicability();
|
|
5990
|
-
if (this.state.drilldownRecommendationsEnabled) {
|
|
5991
|
-
const
|
|
5992
|
-
|
|
5993
|
-
|
|
5994
|
-
this._verifyRecentFiltersApplicability(storedFilters);
|
|
5995
|
-
} else {
|
|
5996
|
-
this.setState({ _recentFilters: [] });
|
|
5997
|
-
}
|
|
5998
|
-
this._fetchRecommendedDrilldowns();
|
|
6212
|
+
if (this.state.drilldownRecommendationsEnabled && !this.state._valueRecommendations) {
|
|
6213
|
+
const valueRecommendations = new AdHocFiltersRecommendations(this);
|
|
6214
|
+
this.setState({ _valueRecommendations: valueRecommendations });
|
|
6215
|
+
valueRecommendations.activate();
|
|
5999
6216
|
}
|
|
6000
6217
|
return () => {
|
|
6001
|
-
var
|
|
6002
|
-
(
|
|
6218
|
+
var _a;
|
|
6219
|
+
(_a = this.state.originFilters) == null ? void 0 : _a.forEach((filter) => {
|
|
6003
6220
|
if (filter.restorable) {
|
|
6004
6221
|
this.restoreOriginalFilter(filter);
|
|
6005
6222
|
}
|
|
@@ -6019,34 +6236,6 @@ class AdHocFiltersVariable extends SceneObjectBase {
|
|
|
6019
6236
|
});
|
|
6020
6237
|
this.addActivationHandler(this._activationHandler);
|
|
6021
6238
|
}
|
|
6022
|
-
async _fetchRecommendedDrilldowns() {
|
|
6023
|
-
var _a;
|
|
6024
|
-
const ds = await this._dataSourceSrv.get(this.state.datasource, this._scopedVars);
|
|
6025
|
-
if (!ds || !ds.getRecommendedDrilldowns) {
|
|
6026
|
-
return;
|
|
6027
|
-
}
|
|
6028
|
-
const queries = this.state.useQueriesAsFilterForOptions ? getQueriesForVariables(this) : void 0;
|
|
6029
|
-
const timeRange = sceneGraph.getTimeRange(this).state.value;
|
|
6030
|
-
const scopes = sceneGraph.getScopes(this);
|
|
6031
|
-
const filters = [...(_a = this.state.originFilters) != null ? _a : [], ...this.state.filters];
|
|
6032
|
-
const enrichedRequest = getEnrichedDataRequest(this);
|
|
6033
|
-
const dashboardUid = enrichedRequest == null ? void 0 : enrichedRequest.dashboardUID;
|
|
6034
|
-
try {
|
|
6035
|
-
const recommendedDrilldowns = await ds.getRecommendedDrilldowns({
|
|
6036
|
-
timeRange,
|
|
6037
|
-
dashboardUid,
|
|
6038
|
-
queries: queries != null ? queries : [],
|
|
6039
|
-
filters,
|
|
6040
|
-
scopes,
|
|
6041
|
-
userId: runtime.config.bootData.user.id
|
|
6042
|
-
});
|
|
6043
|
-
if (recommendedDrilldowns == null ? void 0 : recommendedDrilldowns.filters) {
|
|
6044
|
-
this.setRecommendedFilters(recommendedDrilldowns.filters);
|
|
6045
|
-
}
|
|
6046
|
-
} catch (error) {
|
|
6047
|
-
console.error("Failed to fetch recommended drilldowns:", error);
|
|
6048
|
-
}
|
|
6049
|
-
}
|
|
6050
6239
|
_updateScopesFilters() {
|
|
6051
6240
|
var _a, _b;
|
|
6052
6241
|
const scopes = sceneGraph.getScopes(this);
|
|
@@ -6096,10 +6285,10 @@ class AdHocFiltersVariable extends SceneObjectBase {
|
|
|
6096
6285
|
}
|
|
6097
6286
|
async verifyApplicabilityAndStoreRecentFilter(update) {
|
|
6098
6287
|
await this._verifyApplicability();
|
|
6099
|
-
if (!this.state.drilldownRecommendationsEnabled) {
|
|
6288
|
+
if (!this.state.drilldownRecommendationsEnabled || !this.state._valueRecommendations) {
|
|
6100
6289
|
return;
|
|
6101
6290
|
}
|
|
6102
|
-
this.storeRecentFilter(update);
|
|
6291
|
+
this.state._valueRecommendations.storeRecentFilter(update);
|
|
6103
6292
|
}
|
|
6104
6293
|
setState(update) {
|
|
6105
6294
|
var _a, _b;
|
|
@@ -6206,39 +6395,12 @@ class AdHocFiltersVariable extends SceneObjectBase {
|
|
|
6206
6395
|
return f === filter ? { ...f, ...update } : f;
|
|
6207
6396
|
});
|
|
6208
6397
|
this.setState({ filters: updatedFilters });
|
|
6209
|
-
this.
|
|
6210
|
-
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
return;
|
|
6215
|
-
}
|
|
6216
|
-
const key = getRecentFiltersKey((_a = this.state.datasource) == null ? void 0 : _a.uid);
|
|
6217
|
-
const storedFilters = data.store.get(key);
|
|
6218
|
-
const allRecentFilters = storedFilters ? JSON.parse(storedFilters) : [];
|
|
6219
|
-
const updatedStoredFilters = [...allRecentFilters, update].slice(-10);
|
|
6220
|
-
data.store.set(key, JSON.stringify(updatedStoredFilters));
|
|
6221
|
-
const filter = this.state.filters.find((f) => f.key === update.key && !Boolean(f.nonApplicable));
|
|
6222
|
-
if (filter && !Boolean(filter.nonApplicable)) {
|
|
6223
|
-
this.setState({ _recentFilters: updatedStoredFilters.slice(-3) });
|
|
6224
|
-
}
|
|
6225
|
-
}
|
|
6226
|
-
async _verifyRecentFiltersApplicability(storedFilters) {
|
|
6227
|
-
const queries = this.state.useQueriesAsFilterForOptions ? getQueriesForVariables(this) : void 0;
|
|
6228
|
-
const response = await this.getFiltersApplicabilityForQueries(storedFilters, queries != null ? queries : []);
|
|
6229
|
-
if (!response) {
|
|
6230
|
-
this.setState({ _recentFilters: storedFilters.slice(-3) });
|
|
6231
|
-
return;
|
|
6398
|
+
if (this.state.drilldownRecommendationsEnabled && this.state._valueRecommendations) {
|
|
6399
|
+
this.state._valueRecommendations.storeRecentFilter({
|
|
6400
|
+
...filter,
|
|
6401
|
+
...update
|
|
6402
|
+
});
|
|
6232
6403
|
}
|
|
6233
|
-
const applicabilityMap = /* @__PURE__ */ new Map();
|
|
6234
|
-
response.forEach((item) => {
|
|
6235
|
-
applicabilityMap.set(item.key, item.applicable !== false);
|
|
6236
|
-
});
|
|
6237
|
-
const applicableFilters = storedFilters.filter((f) => {
|
|
6238
|
-
const isApplicable = applicabilityMap.get(f.key);
|
|
6239
|
-
return isApplicable === void 0 || isApplicable === true;
|
|
6240
|
-
}).slice(-3);
|
|
6241
|
-
this.setState({ _recentFilters: applicableFilters });
|
|
6242
6404
|
}
|
|
6243
6405
|
updateToMatchAll(filter) {
|
|
6244
6406
|
this._updateFilter(filter, {
|
|
@@ -6315,11 +6477,6 @@ class AdHocFiltersVariable extends SceneObjectBase {
|
|
|
6315
6477
|
});
|
|
6316
6478
|
}
|
|
6317
6479
|
}
|
|
6318
|
-
setRecommendedFilters(recommendedFilters) {
|
|
6319
|
-
this.setState({
|
|
6320
|
-
_recommendedFilters: recommendedFilters
|
|
6321
|
-
});
|
|
6322
|
-
}
|
|
6323
6480
|
async getFiltersApplicabilityForQueries(filters, queries) {
|
|
6324
6481
|
const ds = await this._dataSourceSrv.get(this.state.datasource, this._scopedVars);
|
|
6325
6482
|
if (!ds || !ds.getDrilldownsApplicability) {
|
|
@@ -6482,64 +6639,237 @@ class AdHocFiltersVariable extends SceneObjectBase {
|
|
|
6482
6639
|
description
|
|
6483
6640
|
}));
|
|
6484
6641
|
}
|
|
6485
|
-
}
|
|
6486
|
-
AdHocFiltersVariable.Component = AdHocFiltersVariableRenderer;
|
|
6487
|
-
function renderExpression(builder, filters) {
|
|
6488
|
-
var _a;
|
|
6489
|
-
return (builder != null ? builder : renderPrometheusLabelFilters)((_a = filters == null ? void 0 : filters.filter((f) => isFilterApplicable(f))) != null ? _a : []);
|
|
6490
|
-
}
|
|
6491
|
-
function AdHocFiltersVariableRenderer({ model }) {
|
|
6492
|
-
const { filters, readOnly, addFilterButtonText } = model.useState();
|
|
6493
|
-
const styles = ui.useStyles2(getStyles$b);
|
|
6494
|
-
const controller = React.useMemo(
|
|
6495
|
-
() => model.state.layout === "combobox" ? new AdHocFiltersVariableController(model) : void 0,
|
|
6496
|
-
[model]
|
|
6497
|
-
);
|
|
6498
|
-
if (controller) {
|
|
6499
|
-
return /* @__PURE__ */ React__default.default.createElement(AdHocFiltersComboboxRenderer, { controller });
|
|
6642
|
+
}
|
|
6643
|
+
AdHocFiltersVariable.Component = AdHocFiltersVariableRenderer;
|
|
6644
|
+
function renderExpression(builder, filters) {
|
|
6645
|
+
var _a;
|
|
6646
|
+
return (builder != null ? builder : renderPrometheusLabelFilters)((_a = filters == null ? void 0 : filters.filter((f) => isFilterApplicable(f))) != null ? _a : []);
|
|
6647
|
+
}
|
|
6648
|
+
function AdHocFiltersVariableRenderer({ model }) {
|
|
6649
|
+
const { filters, readOnly, addFilterButtonText } = model.useState();
|
|
6650
|
+
const styles = ui.useStyles2(getStyles$b);
|
|
6651
|
+
const controller = React.useMemo(
|
|
6652
|
+
() => model.state.layout === "combobox" ? new AdHocFiltersVariableController(model) : void 0,
|
|
6653
|
+
[model]
|
|
6654
|
+
);
|
|
6655
|
+
if (controller) {
|
|
6656
|
+
return /* @__PURE__ */ React__default.default.createElement(AdHocFiltersComboboxRenderer, { controller });
|
|
6657
|
+
}
|
|
6658
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.wrapper }, filters.filter((filter) => !filter.hidden).map((filter, index) => /* @__PURE__ */ React__default.default.createElement(React__default.default.Fragment, { key: index }, /* @__PURE__ */ React__default.default.createElement(AdHocFilterRenderer, { filter, model }))), !readOnly && /* @__PURE__ */ React__default.default.createElement(AdHocFilterBuilder, { model, key: "'builder", addFilterButtonText }));
|
|
6659
|
+
}
|
|
6660
|
+
const getStyles$b = (theme) => ({
|
|
6661
|
+
wrapper: css.css({
|
|
6662
|
+
display: "flex",
|
|
6663
|
+
flexWrap: "wrap",
|
|
6664
|
+
alignItems: "flex-end",
|
|
6665
|
+
columnGap: theme.spacing(2),
|
|
6666
|
+
rowGap: theme.spacing(1)
|
|
6667
|
+
})
|
|
6668
|
+
});
|
|
6669
|
+
function toSelectableValue$1(input) {
|
|
6670
|
+
const { text, value } = input;
|
|
6671
|
+
const result = {
|
|
6672
|
+
// converting text to string due to some edge cases where it can be a number
|
|
6673
|
+
// TODO: remove once https://github.com/grafana/grafana/issues/99021 is closed
|
|
6674
|
+
label: String(text),
|
|
6675
|
+
value: String(value != null ? value : text)
|
|
6676
|
+
};
|
|
6677
|
+
if ("group" in input) {
|
|
6678
|
+
result.group = input.group;
|
|
6679
|
+
}
|
|
6680
|
+
if ("meta" in input) {
|
|
6681
|
+
result.meta = input.meta;
|
|
6682
|
+
}
|
|
6683
|
+
return result;
|
|
6684
|
+
}
|
|
6685
|
+
function isMatchAllFilter(filter) {
|
|
6686
|
+
return filter.operator === "=~" && filter.value === ".*";
|
|
6687
|
+
}
|
|
6688
|
+
function isFilterComplete(filter) {
|
|
6689
|
+
return filter.key !== "" && filter.operator !== "" && filter.value !== "";
|
|
6690
|
+
}
|
|
6691
|
+
function isFilterApplicable(filter) {
|
|
6692
|
+
return !filter.nonApplicable;
|
|
6693
|
+
}
|
|
6694
|
+
function isMultiValueOperator(operatorValue) {
|
|
6695
|
+
const operator = OPERATORS.find((o) => o.value === operatorValue);
|
|
6696
|
+
if (!operator) {
|
|
6697
|
+
return false;
|
|
6698
|
+
}
|
|
6699
|
+
return Boolean(operator.isMulti);
|
|
6700
|
+
}
|
|
6701
|
+
|
|
6702
|
+
class GroupByRecommendations extends SceneObjectBase {
|
|
6703
|
+
constructor(parent) {
|
|
6704
|
+
super({});
|
|
6705
|
+
this._scopedVars = { __sceneObject: wrapInSafeSerializableSceneObject(this) };
|
|
6706
|
+
this._activationHandler = () => {
|
|
6707
|
+
const json = data.store.get(this._getStorageKey());
|
|
6708
|
+
const storedGroupings = json ? JSON.parse(json) : [];
|
|
6709
|
+
if (storedGroupings.length > 0) {
|
|
6710
|
+
this._verifyRecentGroupingsApplicability(storedGroupings);
|
|
6711
|
+
} else {
|
|
6712
|
+
this.setState({ recentGrouping: [] });
|
|
6713
|
+
}
|
|
6714
|
+
this._fetchRecommendedDrilldowns();
|
|
6715
|
+
const scopesVariable = sceneGraph.lookupVariable(SCOPES_VARIABLE_NAME, this);
|
|
6716
|
+
let scopesSubscription;
|
|
6717
|
+
if (scopesVariable instanceof ScopesVariable) {
|
|
6718
|
+
scopesSubscription = scopesVariable.subscribeToState((newState, prevState) => {
|
|
6719
|
+
if (newState.scopes !== prevState.scopes) {
|
|
6720
|
+
const json2 = data.store.get(this._getStorageKey());
|
|
6721
|
+
const storedGroupings2 = json2 ? JSON.parse(json2) : [];
|
|
6722
|
+
if (storedGroupings2.length > 0) {
|
|
6723
|
+
this._verifyRecentGroupingsApplicability(storedGroupings2);
|
|
6724
|
+
}
|
|
6725
|
+
}
|
|
6726
|
+
});
|
|
6727
|
+
}
|
|
6728
|
+
return () => {
|
|
6729
|
+
scopesSubscription == null ? void 0 : scopesSubscription.unsubscribe();
|
|
6730
|
+
};
|
|
6731
|
+
};
|
|
6732
|
+
this._parentVariable = parent;
|
|
6733
|
+
this.addActivationHandler(this._activationHandler);
|
|
6734
|
+
}
|
|
6735
|
+
/**
|
|
6736
|
+
* Get the parent variable
|
|
6737
|
+
*/
|
|
6738
|
+
get parent() {
|
|
6739
|
+
return this._parentVariable;
|
|
6740
|
+
}
|
|
6741
|
+
_getStorageKey() {
|
|
6742
|
+
var _a;
|
|
6743
|
+
return getRecentGroupingKey((_a = this._parentVariable.state.datasource) == null ? void 0 : _a.uid);
|
|
6744
|
+
}
|
|
6745
|
+
async _fetchRecommendedDrilldowns() {
|
|
6746
|
+
const parent = this._parentVariable;
|
|
6747
|
+
const ds = await getDataSource(parent.state.datasource, this._scopedVars);
|
|
6748
|
+
if (!ds || !ds.getRecommendedDrilldowns) {
|
|
6749
|
+
return;
|
|
6750
|
+
}
|
|
6751
|
+
const queries = getQueriesForVariables(parent);
|
|
6752
|
+
const timeRange = sceneGraph.getTimeRange(this).state.value;
|
|
6753
|
+
const scopes = sceneGraph.getScopes(this);
|
|
6754
|
+
const groupByKeys = Array.isArray(parent.state.value) ? parent.state.value.map((v) => String(v)) : parent.state.value ? [String(parent.state.value)] : [];
|
|
6755
|
+
const enrichedRequest = getEnrichedDataRequest(this);
|
|
6756
|
+
const dashboardUid = enrichedRequest == null ? void 0 : enrichedRequest.dashboardUID;
|
|
6757
|
+
try {
|
|
6758
|
+
const recommendedDrilldowns = await ds.getRecommendedDrilldowns({
|
|
6759
|
+
timeRange,
|
|
6760
|
+
dashboardUid,
|
|
6761
|
+
queries,
|
|
6762
|
+
groupByKeys,
|
|
6763
|
+
scopes,
|
|
6764
|
+
userId: runtime.config.bootData.user.id
|
|
6765
|
+
});
|
|
6766
|
+
if (recommendedDrilldowns == null ? void 0 : recommendedDrilldowns.groupByKeys) {
|
|
6767
|
+
this.setState({
|
|
6768
|
+
recommendedGrouping: recommendedDrilldowns.groupByKeys.map((key) => ({ value: key, text: key }))
|
|
6769
|
+
});
|
|
6770
|
+
}
|
|
6771
|
+
} catch (error) {
|
|
6772
|
+
console.error("Failed to fetch recommended drilldowns:", error);
|
|
6773
|
+
}
|
|
6774
|
+
}
|
|
6775
|
+
async _verifyRecentGroupingsApplicability(storedGroupings) {
|
|
6776
|
+
const queries = getQueriesForVariables(this._parentVariable);
|
|
6777
|
+
const keys = storedGroupings.map((g) => String(g.value));
|
|
6778
|
+
const response = await this._getGroupByApplicabilityForQueries(keys, queries);
|
|
6779
|
+
if (!response) {
|
|
6780
|
+
this.setState({ recentGrouping: storedGroupings.slice(-3) });
|
|
6781
|
+
return;
|
|
6782
|
+
}
|
|
6783
|
+
const applicabilityMap = /* @__PURE__ */ new Map();
|
|
6784
|
+
response.forEach((item) => {
|
|
6785
|
+
applicabilityMap.set(item.key, item.applicable !== false);
|
|
6786
|
+
});
|
|
6787
|
+
const applicableGroupings = storedGroupings.filter((g) => {
|
|
6788
|
+
const isApplicable = applicabilityMap.get(String(g.value));
|
|
6789
|
+
return isApplicable === void 0 || isApplicable === true;
|
|
6790
|
+
}).slice(-3);
|
|
6791
|
+
this.setState({ recentGrouping: applicableGroupings });
|
|
6792
|
+
}
|
|
6793
|
+
async _getGroupByApplicabilityForQueries(value, queries) {
|
|
6794
|
+
const parent = this._parentVariable;
|
|
6795
|
+
const ds = await getDataSource(parent.state.datasource, this._scopedVars);
|
|
6796
|
+
if (!ds || !ds.getDrilldownsApplicability) {
|
|
6797
|
+
return;
|
|
6798
|
+
}
|
|
6799
|
+
const timeRange = sceneGraph.getTimeRange(this).state.value;
|
|
6800
|
+
return await ds.getDrilldownsApplicability({
|
|
6801
|
+
groupByKeys: Array.isArray(value) ? value.map((v) => String(v)) : value ? [String(value)] : [],
|
|
6802
|
+
queries,
|
|
6803
|
+
timeRange,
|
|
6804
|
+
scopes: sceneGraph.getScopes(this),
|
|
6805
|
+
...getEnrichedFiltersRequest(this)
|
|
6806
|
+
});
|
|
6807
|
+
}
|
|
6808
|
+
/**
|
|
6809
|
+
* Stores recent groupings in localStorage and updates state.
|
|
6810
|
+
* Should be called by the parent variable when a grouping is added/updated.
|
|
6811
|
+
*/
|
|
6812
|
+
storeRecentGrouping(applicableValues) {
|
|
6813
|
+
if (applicableValues.length === 0) {
|
|
6814
|
+
return;
|
|
6815
|
+
}
|
|
6816
|
+
const key = this._getStorageKey();
|
|
6817
|
+
const storedGroupings = data.store.get(key);
|
|
6818
|
+
const allRecentGroupings = storedGroupings ? JSON.parse(storedGroupings) : [];
|
|
6819
|
+
const existingWithoutApplicableValues = allRecentGroupings.filter(
|
|
6820
|
+
(grouping) => !applicableValues.includes(String(grouping.value))
|
|
6821
|
+
);
|
|
6822
|
+
const updatedStoredGroupings = [
|
|
6823
|
+
...existingWithoutApplicableValues,
|
|
6824
|
+
...applicableValues.map((value) => ({ value, text: value }))
|
|
6825
|
+
];
|
|
6826
|
+
const limitedStoredGroupings = updatedStoredGroupings.slice(-10);
|
|
6827
|
+
data.store.set(key, JSON.stringify(limitedStoredGroupings));
|
|
6828
|
+
this.setState({ recentGrouping: limitedStoredGroupings.slice(-3) });
|
|
6500
6829
|
}
|
|
6501
|
-
|
|
6502
|
-
|
|
6503
|
-
|
|
6504
|
-
|
|
6505
|
-
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
rowGap: theme.spacing(1)
|
|
6510
|
-
})
|
|
6511
|
-
});
|
|
6512
|
-
function toSelectableValue$1(input) {
|
|
6513
|
-
const { text, value } = input;
|
|
6514
|
-
const result = {
|
|
6515
|
-
// converting text to string due to some edge cases where it can be a number
|
|
6516
|
-
// TODO: remove once https://github.com/grafana/grafana/issues/99021 is closed
|
|
6517
|
-
label: String(text),
|
|
6518
|
-
value: String(value != null ? value : text)
|
|
6519
|
-
};
|
|
6520
|
-
if ("group" in input) {
|
|
6521
|
-
result.group = input.group;
|
|
6830
|
+
/**
|
|
6831
|
+
* Get the current values from the parent variable
|
|
6832
|
+
*/
|
|
6833
|
+
getParentValues() {
|
|
6834
|
+
const parent = this._parentVariable;
|
|
6835
|
+
const value = lodash.isArray(parent.state.value) ? parent.state.value : [parent.state.value];
|
|
6836
|
+
const text = lodash.isArray(parent.state.text) ? parent.state.text.map(String) : [String(parent.state.text)];
|
|
6837
|
+
return { value, text };
|
|
6522
6838
|
}
|
|
6523
|
-
|
|
6524
|
-
|
|
6839
|
+
/**
|
|
6840
|
+
* Add a grouping value to the parent variable
|
|
6841
|
+
*/
|
|
6842
|
+
addValueToParent(newValue, newText) {
|
|
6843
|
+
const parent = this._parentVariable;
|
|
6844
|
+
const { value, text } = this.getParentValues();
|
|
6845
|
+
if (value.includes(newValue)) {
|
|
6846
|
+
return;
|
|
6847
|
+
}
|
|
6848
|
+
parent.changeValueTo(
|
|
6849
|
+
[...value.filter((v) => v !== ""), newValue],
|
|
6850
|
+
[...text.filter((t) => t !== ""), newText != null ? newText : String(newValue)],
|
|
6851
|
+
true
|
|
6852
|
+
);
|
|
6525
6853
|
}
|
|
6526
|
-
return result;
|
|
6527
|
-
}
|
|
6528
|
-
function isMatchAllFilter(filter) {
|
|
6529
|
-
return filter.operator === "=~" && filter.value === ".*";
|
|
6530
|
-
}
|
|
6531
|
-
function isFilterComplete(filter) {
|
|
6532
|
-
return filter.key !== "" && filter.operator !== "" && filter.value !== "";
|
|
6533
|
-
}
|
|
6534
|
-
function isFilterApplicable(filter) {
|
|
6535
|
-
return !filter.nonApplicable;
|
|
6536
6854
|
}
|
|
6537
|
-
|
|
6538
|
-
|
|
6539
|
-
|
|
6540
|
-
|
|
6541
|
-
|
|
6542
|
-
|
|
6855
|
+
GroupByRecommendations.Component = GroupByRecommendationsRenderer;
|
|
6856
|
+
function GroupByRecommendationsRenderer({ model }) {
|
|
6857
|
+
const { recentGrouping, recommendedGrouping } = model.useState();
|
|
6858
|
+
const recentDrilldowns = recentGrouping == null ? void 0 : recentGrouping.map((groupBy) => ({
|
|
6859
|
+
label: `${groupBy.value}`,
|
|
6860
|
+
onClick: () => {
|
|
6861
|
+
var _a;
|
|
6862
|
+
model.addValueToParent(groupBy.value, (_a = groupBy.text) != null ? _a : String(groupBy.value));
|
|
6863
|
+
}
|
|
6864
|
+
}));
|
|
6865
|
+
const recommendedDrilldowns = recommendedGrouping == null ? void 0 : recommendedGrouping.map((groupBy) => ({
|
|
6866
|
+
label: `${groupBy.value}`,
|
|
6867
|
+
onClick: () => {
|
|
6868
|
+
var _a;
|
|
6869
|
+
model.addValueToParent(groupBy.value, (_a = groupBy.text) != null ? _a : String(groupBy.value));
|
|
6870
|
+
}
|
|
6871
|
+
}));
|
|
6872
|
+
return /* @__PURE__ */ React__default.default.createElement(DrilldownRecommendations, { recentDrilldowns, recommendedDrilldowns });
|
|
6543
6873
|
}
|
|
6544
6874
|
|
|
6545
6875
|
const getRecentGroupingKey = (datasourceUid) => `grafana.grouping.recent.${datasourceUid != null ? datasourceUid : "default"}`;
|
|
@@ -6562,22 +6892,16 @@ class GroupByVariable extends MultiValueVariable {
|
|
|
6562
6892
|
this.isLazy = true;
|
|
6563
6893
|
this._urlSync = new GroupByVariableUrlSyncHandler(this);
|
|
6564
6894
|
this._activationHandler = () => {
|
|
6565
|
-
var _a;
|
|
6566
6895
|
this._verifyApplicability();
|
|
6567
6896
|
if (this.state.defaultValue) {
|
|
6568
6897
|
if (this.checkIfRestorable(this.state.value)) {
|
|
6569
6898
|
this.setState({ restorable: true });
|
|
6570
6899
|
}
|
|
6571
6900
|
}
|
|
6572
|
-
if (this.state.drilldownRecommendationsEnabled) {
|
|
6573
|
-
const
|
|
6574
|
-
|
|
6575
|
-
|
|
6576
|
-
this._verifyRecentGroupingsApplicability(storedGroupings);
|
|
6577
|
-
} else {
|
|
6578
|
-
this.setState({ _recentGrouping: [] });
|
|
6579
|
-
}
|
|
6580
|
-
this._fetchRecommendedDrilldowns();
|
|
6901
|
+
if (this.state.drilldownRecommendationsEnabled && !this.state._valueRecommendations) {
|
|
6902
|
+
const valueRecommendations = new GroupByRecommendations(this);
|
|
6903
|
+
this.setState({ _valueRecommendations: valueRecommendations });
|
|
6904
|
+
valueRecommendations.activate();
|
|
6581
6905
|
}
|
|
6582
6906
|
return () => {
|
|
6583
6907
|
if (this.state.defaultValue) {
|
|
@@ -6692,53 +7016,6 @@ class GroupByVariable extends MultiValueVariable {
|
|
|
6692
7016
|
})
|
|
6693
7017
|
);
|
|
6694
7018
|
}
|
|
6695
|
-
async _verifyRecentGroupingsApplicability(storedGroupings) {
|
|
6696
|
-
const queries = getQueriesForVariables(this);
|
|
6697
|
-
const keys = storedGroupings.map((g) => String(g.value));
|
|
6698
|
-
const response = await this.getGroupByApplicabilityForQueries(keys, queries);
|
|
6699
|
-
if (!response) {
|
|
6700
|
-
this.setState({ _recentGrouping: storedGroupings.slice(-3) });
|
|
6701
|
-
return;
|
|
6702
|
-
}
|
|
6703
|
-
const applicabilityMap = /* @__PURE__ */ new Map();
|
|
6704
|
-
response.forEach((item) => {
|
|
6705
|
-
applicabilityMap.set(item.key, item.applicable !== false);
|
|
6706
|
-
});
|
|
6707
|
-
const applicableGroupings = storedGroupings.filter((g) => {
|
|
6708
|
-
const isApplicable = applicabilityMap.get(String(g.value));
|
|
6709
|
-
return isApplicable === void 0 || isApplicable === true;
|
|
6710
|
-
}).slice(-3);
|
|
6711
|
-
this.setState({ _recentGrouping: applicableGroupings });
|
|
6712
|
-
}
|
|
6713
|
-
async _fetchRecommendedDrilldowns() {
|
|
6714
|
-
const ds = await getDataSource(this.state.datasource, {
|
|
6715
|
-
__sceneObject: wrapInSafeSerializableSceneObject(this)
|
|
6716
|
-
});
|
|
6717
|
-
if (!ds || !ds.getRecommendedDrilldowns) {
|
|
6718
|
-
return;
|
|
6719
|
-
}
|
|
6720
|
-
const queries = getQueriesForVariables(this);
|
|
6721
|
-
const timeRange = sceneGraph.getTimeRange(this).state.value;
|
|
6722
|
-
const scopes = sceneGraph.getScopes(this);
|
|
6723
|
-
const groupByKeys = Array.isArray(this.state.value) ? this.state.value.map((v) => String(v)) : this.state.value ? [String(this.state.value)] : [];
|
|
6724
|
-
const enrichedRequest = getEnrichedDataRequest(this);
|
|
6725
|
-
const dashboardUid = enrichedRequest == null ? void 0 : enrichedRequest.dashboardUID;
|
|
6726
|
-
try {
|
|
6727
|
-
const recommendedDrilldowns = await ds.getRecommendedDrilldowns({
|
|
6728
|
-
timeRange,
|
|
6729
|
-
dashboardUid,
|
|
6730
|
-
queries,
|
|
6731
|
-
groupByKeys,
|
|
6732
|
-
scopes,
|
|
6733
|
-
userId: runtime.config.bootData.user.id
|
|
6734
|
-
});
|
|
6735
|
-
if (recommendedDrilldowns == null ? void 0 : recommendedDrilldowns.groupByKeys) {
|
|
6736
|
-
this.setRecommendedGrouping(recommendedDrilldowns.groupByKeys);
|
|
6737
|
-
}
|
|
6738
|
-
} catch (error) {
|
|
6739
|
-
console.error("Failed to fetch recommended drilldowns:", error);
|
|
6740
|
-
}
|
|
6741
|
-
}
|
|
6742
7019
|
getApplicableKeys() {
|
|
6743
7020
|
const { value, keysApplicability } = this.state;
|
|
6744
7021
|
const valueArray = lodash.isArray(value) ? value.map(String) : value ? [String(value)] : [];
|
|
@@ -6801,33 +7078,15 @@ class GroupByVariable extends MultiValueVariable {
|
|
|
6801
7078
|
this.changeValueTo(this.state.defaultValue.value, this.state.defaultValue.text, true);
|
|
6802
7079
|
}
|
|
6803
7080
|
async _verifyApplicabilityAndStoreRecentGrouping() {
|
|
6804
|
-
var _a;
|
|
6805
7081
|
await this._verifyApplicability();
|
|
6806
|
-
if (!this.state.drilldownRecommendationsEnabled) {
|
|
7082
|
+
if (!this.state.drilldownRecommendationsEnabled || !this.state._valueRecommendations) {
|
|
6807
7083
|
return;
|
|
6808
7084
|
}
|
|
6809
7085
|
const applicableValues = this.getApplicableKeys();
|
|
6810
7086
|
if (applicableValues.length === 0) {
|
|
6811
7087
|
return;
|
|
6812
7088
|
}
|
|
6813
|
-
|
|
6814
|
-
const storedGroupings = data.store.get(key);
|
|
6815
|
-
const allRecentGroupings = storedGroupings ? JSON.parse(storedGroupings) : [];
|
|
6816
|
-
const existingWithoutApplicableValues = allRecentGroupings.filter(
|
|
6817
|
-
(grouping) => !applicableValues.includes(String(grouping.value))
|
|
6818
|
-
);
|
|
6819
|
-
const updatedStoredGroupings = [
|
|
6820
|
-
...existingWithoutApplicableValues,
|
|
6821
|
-
...applicableValues.map((value) => ({ value, text: value }))
|
|
6822
|
-
];
|
|
6823
|
-
const limitedStoredGroupings = updatedStoredGroupings.slice(-10);
|
|
6824
|
-
data.store.set(key, JSON.stringify(limitedStoredGroupings));
|
|
6825
|
-
this.setState({ _recentGrouping: limitedStoredGroupings.slice(-3) });
|
|
6826
|
-
}
|
|
6827
|
-
setRecommendedGrouping(recommendedGrouping) {
|
|
6828
|
-
this.setState({
|
|
6829
|
-
_recommendedGrouping: recommendedGrouping.map((key) => ({ value: key, text: key }))
|
|
6830
|
-
});
|
|
7089
|
+
this.state._valueRecommendations.storeRecentGrouping(applicableValues);
|
|
6831
7090
|
}
|
|
6832
7091
|
/**
|
|
6833
7092
|
* Allows clearing the value of the variable to an empty value. Overrides default behavior of a MultiValueVariable
|
|
@@ -6850,8 +7109,7 @@ function GroupByVariableRenderer({ model }) {
|
|
|
6850
7109
|
allowCustomValue = true,
|
|
6851
7110
|
defaultValue,
|
|
6852
7111
|
keysApplicability,
|
|
6853
|
-
|
|
6854
|
-
_recommendedGrouping,
|
|
7112
|
+
_valueRecommendations,
|
|
6855
7113
|
drilldownRecommendationsEnabled
|
|
6856
7114
|
} = model.useState();
|
|
6857
7115
|
const styles = ui.useStyles2(getStyles$a);
|
|
@@ -7022,38 +7280,10 @@ function GroupByVariableRenderer({ model }) {
|
|
|
7022
7280
|
}
|
|
7023
7281
|
}
|
|
7024
7282
|
);
|
|
7025
|
-
if (!drilldownRecommendationsEnabled) {
|
|
7283
|
+
if (!drilldownRecommendationsEnabled || !_valueRecommendations) {
|
|
7026
7284
|
return select;
|
|
7027
7285
|
}
|
|
7028
|
-
|
|
7029
|
-
label: `${groupBy.value}`,
|
|
7030
|
-
onClick: () => {
|
|
7031
|
-
var _a;
|
|
7032
|
-
if (values.map((x) => x.value).includes(groupBy.value)) {
|
|
7033
|
-
return;
|
|
7034
|
-
}
|
|
7035
|
-
model.changeValueTo(
|
|
7036
|
-
[...values.map((x) => x.value), groupBy.value],
|
|
7037
|
-
[...values.map((x) => x.label), (_a = groupBy.text) != null ? _a : groupBy.value],
|
|
7038
|
-
true
|
|
7039
|
-
);
|
|
7040
|
-
}
|
|
7041
|
-
}));
|
|
7042
|
-
const recommendedDrilldowns = _recommendedGrouping == null ? void 0 : _recommendedGrouping.map((groupBy) => ({
|
|
7043
|
-
label: `${groupBy.value}`,
|
|
7044
|
-
onClick: () => {
|
|
7045
|
-
var _a;
|
|
7046
|
-
if (values.map((x) => x.value).includes(groupBy.value)) {
|
|
7047
|
-
return;
|
|
7048
|
-
}
|
|
7049
|
-
model.changeValueTo(
|
|
7050
|
-
[...values.map((x) => x.value), groupBy.value],
|
|
7051
|
-
[...values.map((x) => x.label), (_a = groupBy.text) != null ? _a : groupBy.value],
|
|
7052
|
-
true
|
|
7053
|
-
);
|
|
7054
|
-
}
|
|
7055
|
-
}));
|
|
7056
|
-
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.wrapper }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.recommendations }, /* @__PURE__ */ React__default.default.createElement(DrilldownRecommendations, { recentDrilldowns, recommendedDrilldowns })), select);
|
|
7286
|
+
return /* @__PURE__ */ React__default.default.createElement("div", { className: styles.wrapper }, /* @__PURE__ */ React__default.default.createElement("div", { className: styles.recommendations }, /* @__PURE__ */ React__default.default.createElement(_valueRecommendations.Component, { model: _valueRecommendations })), select);
|
|
7057
7287
|
}
|
|
7058
7288
|
const filterNoOp = () => true;
|
|
7059
7289
|
function WideMenu(props) {
|
|
@@ -10306,91 +10536,6 @@ function containsSearchFilter(query) {
|
|
|
10306
10536
|
return str.indexOf(SEARCH_FILTER_VARIABLE) > -1;
|
|
10307
10537
|
}
|
|
10308
10538
|
|
|
10309
|
-
class ScopesVariable extends SceneObjectBase {
|
|
10310
|
-
constructor(state) {
|
|
10311
|
-
super({
|
|
10312
|
-
skipUrlSync: true,
|
|
10313
|
-
loading: true,
|
|
10314
|
-
scopes: [],
|
|
10315
|
-
...state,
|
|
10316
|
-
type: "system",
|
|
10317
|
-
name: SCOPES_VARIABLE_NAME,
|
|
10318
|
-
hide: schema.VariableHide.hideVariable
|
|
10319
|
-
});
|
|
10320
|
-
this._renderBeforeActivation = true;
|
|
10321
|
-
// Special options that enables variables to be hidden but still render to access react contexts
|
|
10322
|
-
this.UNSAFE_renderAsHidden = true;
|
|
10323
|
-
}
|
|
10324
|
-
/**
|
|
10325
|
-
* Temporary simple implementation to stringify the scopes.
|
|
10326
|
-
*/
|
|
10327
|
-
getValue() {
|
|
10328
|
-
var _a;
|
|
10329
|
-
const scopes = (_a = this.state.scopes) != null ? _a : [];
|
|
10330
|
-
return new ScopesVariableFormatter(scopes.map((scope) => scope.metadata.name));
|
|
10331
|
-
}
|
|
10332
|
-
getScopes() {
|
|
10333
|
-
return this.state.scopes;
|
|
10334
|
-
}
|
|
10335
|
-
/**
|
|
10336
|
-
* This method is used to keep the context up to date with the scopes context received from React
|
|
10337
|
-
* 1) Subscribes to ScopesContext state changes and synchronizes it with the variable state
|
|
10338
|
-
* 2) Handles enable / disabling of scopes based on variable enable option.
|
|
10339
|
-
*/
|
|
10340
|
-
setContext(context) {
|
|
10341
|
-
if (!context) {
|
|
10342
|
-
return;
|
|
10343
|
-
}
|
|
10344
|
-
this._context = context;
|
|
10345
|
-
const oldState = context.state;
|
|
10346
|
-
if (this.state.enable != null) {
|
|
10347
|
-
context.setEnabled(this.state.enable);
|
|
10348
|
-
}
|
|
10349
|
-
const sub = context.stateObservable.subscribe((state) => {
|
|
10350
|
-
this.updateStateFromContext(state);
|
|
10351
|
-
});
|
|
10352
|
-
return () => {
|
|
10353
|
-
sub.unsubscribe();
|
|
10354
|
-
if (this.state.enable != null) {
|
|
10355
|
-
context.setEnabled(oldState.enabled);
|
|
10356
|
-
}
|
|
10357
|
-
};
|
|
10358
|
-
}
|
|
10359
|
-
updateStateFromContext(state) {
|
|
10360
|
-
const loading = state.value.length === 0 ? false : state.loading;
|
|
10361
|
-
const oldScopes = this.state.scopes.map((scope) => scope.metadata.name);
|
|
10362
|
-
const newScopes = state.value.map((scope) => scope.metadata.name);
|
|
10363
|
-
const scopesHaveChanged = !lodash.isEqual(oldScopes, newScopes);
|
|
10364
|
-
if (!loading && (scopesHaveChanged || newScopes.length === 0)) {
|
|
10365
|
-
const queryController = getQueryController(this);
|
|
10366
|
-
queryController == null ? void 0 : queryController.startProfile(SCOPES_CHANGED_INTERACTION);
|
|
10367
|
-
this.setState({ scopes: state.value, loading });
|
|
10368
|
-
this.publishEvent(new SceneVariableValueChangedEvent(this), true);
|
|
10369
|
-
} else {
|
|
10370
|
-
this.setState({ loading });
|
|
10371
|
-
}
|
|
10372
|
-
}
|
|
10373
|
-
}
|
|
10374
|
-
ScopesVariable.Component = ScopesVariableRenderer;
|
|
10375
|
-
function ScopesVariableRenderer({ model }) {
|
|
10376
|
-
const context = React.useContext(runtime.ScopesContext);
|
|
10377
|
-
React.useEffect(() => {
|
|
10378
|
-
return model.setContext(context);
|
|
10379
|
-
}, [context, model]);
|
|
10380
|
-
return null;
|
|
10381
|
-
}
|
|
10382
|
-
class ScopesVariableFormatter {
|
|
10383
|
-
constructor(_value) {
|
|
10384
|
-
this._value = _value;
|
|
10385
|
-
}
|
|
10386
|
-
formatter(formatNameOrFn) {
|
|
10387
|
-
if (formatNameOrFn === schema.VariableFormatID.QueryParam) {
|
|
10388
|
-
return this._value.map((scope) => `scope=${encodeURIComponent(scope)}`).join("&");
|
|
10389
|
-
}
|
|
10390
|
-
return this._value.join(", ");
|
|
10391
|
-
}
|
|
10392
|
-
}
|
|
10393
|
-
|
|
10394
10539
|
function getVariables(sceneObject) {
|
|
10395
10540
|
var _a;
|
|
10396
10541
|
return (_a = getClosest(sceneObject, (s) => s.state.$variables)) != null ? _a : EmptyVariableSet;
|