@grafana/scenes 6.50.0--canary.1312.20243507649.0 → 6.50.0--canary.1316.20252812955.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.
Files changed (31) hide show
  1. package/dist/esm/packages/scenes/src/index.js +1 -1
  2. package/dist/esm/packages/scenes/src/index.js.map +1 -1
  3. package/dist/esm/packages/scenes/src/locales/en-US/grafana-scenes.json.js +6 -7
  4. package/dist/esm/packages/scenes/src/locales/en-US/grafana-scenes.json.js.map +1 -1
  5. package/dist/esm/packages/scenes/src/variables/DrilldownDependenciesManager.js.map +1 -1
  6. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersAlwaysWipCombobox.js +2 -2
  7. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersAlwaysWipCombobox.js.map +1 -1
  8. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js +3 -1
  9. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersCombobox.js.map +1 -1
  10. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersComboboxRenderer.js +110 -23
  11. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/AdHocFiltersComboboxRenderer.js.map +1 -1
  12. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/utils.js +3 -0
  13. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersCombobox/utils.js.map +1 -1
  14. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersVariable.js +15 -26
  15. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersVariable.js.map +1 -1
  16. package/dist/esm/packages/scenes/src/variables/adhoc/controller/AdHocFiltersVariableController.js +4 -5
  17. package/dist/esm/packages/scenes/src/variables/adhoc/controller/AdHocFiltersVariableController.js.map +1 -1
  18. package/dist/esm/packages/scenes/src/variables/groupby/GroupByVariable.js +7 -59
  19. package/dist/esm/packages/scenes/src/variables/groupby/GroupByVariable.js.map +1 -1
  20. package/dist/{grafana-scenes-C9F_2hih.js → grafana-scenes-CwGWCTcQ.js} +7 -8
  21. package/dist/{grafana-scenes-C9F_2hih.js.map → grafana-scenes-CwGWCTcQ.js.map} +1 -1
  22. package/dist/index.d.ts +18 -127
  23. package/dist/index.js +225 -624
  24. package/dist/index.js.map +1 -1
  25. package/package.json +2 -2
  26. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersRecommendations.js +0 -174
  27. package/dist/esm/packages/scenes/src/variables/adhoc/AdHocFiltersRecommendations.js.map +0 -1
  28. package/dist/esm/packages/scenes/src/variables/components/DrilldownRecommendations.js +0 -102
  29. package/dist/esm/packages/scenes/src/variables/components/DrilldownRecommendations.js.map +0 -1
  30. package/dist/esm/packages/scenes/src/variables/groupby/GroupByRecommendations.js +0 -192
  31. package/dist/esm/packages/scenes/src/variables/groupby/GroupByRecommendations.js.map +0 -1
package/dist/index.js CHANGED
@@ -3458,7 +3458,7 @@ function wrapInSafeSerializableSceneObject(sceneObject) {
3458
3458
  function DefaultGroupByCustomIndicatorContainer(props) {
3459
3459
  const { model } = props;
3460
3460
  const theme = ui.useTheme2();
3461
- const styles = getStyles$l(theme);
3461
+ const styles = getStyles$j(theme);
3462
3462
  const inputStyles = ui.getInputStyles({ theme, invalid: false });
3463
3463
  const value = lodash.isArray(model.state.value) ? model.state.value : model.state.value ? [model.state.value] : [];
3464
3464
  let buttons = [];
@@ -3540,7 +3540,7 @@ function DefaultGroupByCustomIndicatorContainer(props) {
3540
3540
  buttons
3541
3541
  );
3542
3542
  }
3543
- const getStyles$l = (theme) => ({
3543
+ const getStyles$j = (theme) => ({
3544
3544
  clearIcon: css.css({
3545
3545
  color: theme.colors.action.disabledText,
3546
3546
  cursor: "pointer",
@@ -3614,518 +3614,6 @@ 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
-
3797
- const getRecentFiltersKey = (datasourceUid) => `grafana.filters.recent.${datasourceUid != null ? datasourceUid : "default"}`;
3798
- class AdHocFiltersRecommendations extends SceneObjectBase {
3799
- constructor(parent) {
3800
- super({});
3801
- this._scopedVars = { __sceneObject: wrapInSafeSerializableSceneObject(this) };
3802
- this._activationHandler = () => {
3803
- const json = data.store.get(this._getStorageKey());
3804
- const storedFilters = json ? JSON.parse(json) : [];
3805
- if (storedFilters.length > 0) {
3806
- this._verifyRecentFiltersApplicability(storedFilters);
3807
- } else {
3808
- this.setState({ recentFilters: [] });
3809
- }
3810
- this._fetchRecommendedDrilldowns();
3811
- const scopesVariable = sceneGraph.lookupVariable(SCOPES_VARIABLE_NAME, this);
3812
- let scopesSubscription;
3813
- if (scopesVariable instanceof ScopesVariable) {
3814
- scopesSubscription = scopesVariable.subscribeToState((newState, prevState) => {
3815
- if (newState.scopes !== prevState.scopes) {
3816
- const json2 = data.store.get(this._getStorageKey());
3817
- const storedFilters2 = json2 ? JSON.parse(json2) : [];
3818
- if (storedFilters2.length > 0) {
3819
- this._verifyRecentFiltersApplicability(storedFilters2);
3820
- }
3821
- }
3822
- });
3823
- }
3824
- return () => {
3825
- scopesSubscription == null ? void 0 : scopesSubscription.unsubscribe();
3826
- };
3827
- };
3828
- this._parentVariable = parent;
3829
- this.addActivationHandler(this._activationHandler);
3830
- }
3831
- /**
3832
- * Get the parent variable
3833
- */
3834
- get parent() {
3835
- return this._parentVariable;
3836
- }
3837
- _getStorageKey() {
3838
- var _a;
3839
- return getRecentFiltersKey((_a = this._parentVariable.state.datasource) == null ? void 0 : _a.uid);
3840
- }
3841
- async _fetchRecommendedDrilldowns() {
3842
- var _a;
3843
- const parent = this._parentVariable;
3844
- const ds = await getDataSource(parent.state.datasource, this._scopedVars);
3845
- if (!ds || !ds.getRecommendedDrilldowns) {
3846
- return;
3847
- }
3848
- const queries = parent.state.useQueriesAsFilterForOptions ? getQueriesForVariables(parent) : void 0;
3849
- const timeRange = sceneGraph.getTimeRange(this).state.value;
3850
- const scopes = sceneGraph.getScopes(this);
3851
- const filters = [...(_a = parent.state.originFilters) != null ? _a : [], ...parent.state.filters];
3852
- const enrichedRequest = getEnrichedDataRequest(this);
3853
- const dashboardUid = enrichedRequest == null ? void 0 : enrichedRequest.dashboardUID;
3854
- try {
3855
- const recommendedDrilldowns = await ds.getRecommendedDrilldowns({
3856
- timeRange,
3857
- dashboardUid,
3858
- queries: queries != null ? queries : [],
3859
- filters,
3860
- scopes,
3861
- userId: runtime.config.bootData.user.id
3862
- });
3863
- if (recommendedDrilldowns == null ? void 0 : recommendedDrilldowns.filters) {
3864
- this.setState({ recommendedFilters: recommendedDrilldowns.filters });
3865
- }
3866
- } catch (error) {
3867
- console.error("Failed to fetch recommended drilldowns:", error);
3868
- }
3869
- }
3870
- async _verifyRecentFiltersApplicability(storedFilters) {
3871
- const parent = this._parentVariable;
3872
- const queries = parent.state.useQueriesAsFilterForOptions ? getQueriesForVariables(parent) : void 0;
3873
- const response = await this._getFiltersApplicabilityForQueries(storedFilters, queries != null ? queries : []);
3874
- if (!response) {
3875
- this.setState({ recentFilters: storedFilters.slice(-3) });
3876
- return;
3877
- }
3878
- const applicabilityMap = /* @__PURE__ */ new Map();
3879
- response.forEach((item) => {
3880
- applicabilityMap.set(item.key, item.applicable !== false);
3881
- });
3882
- const applicableFilters = storedFilters.filter((f) => {
3883
- const isApplicable = applicabilityMap.get(f.key);
3884
- return isApplicable === void 0 || isApplicable === true;
3885
- }).slice(-3);
3886
- this.setState({ recentFilters: applicableFilters });
3887
- }
3888
- async _getFiltersApplicabilityForQueries(filters, queries) {
3889
- const parent = this._parentVariable;
3890
- const ds = await getDataSource(parent.state.datasource, this._scopedVars);
3891
- if (!ds || !ds.getDrilldownsApplicability) {
3892
- return;
3893
- }
3894
- const timeRange = sceneGraph.getTimeRange(this).state.value;
3895
- return await ds.getDrilldownsApplicability({
3896
- filters,
3897
- queries,
3898
- timeRange,
3899
- scopes: sceneGraph.getScopes(this),
3900
- ...getEnrichedFiltersRequest(this)
3901
- });
3902
- }
3903
- /**
3904
- * Stores a recent filter in localStorage and updates state.
3905
- * Should be called by the parent variable when a filter is added/updated.
3906
- */
3907
- storeRecentFilter(filter) {
3908
- const key = this._getStorageKey();
3909
- const storedFilters = data.store.get(key);
3910
- const allRecentFilters = storedFilters ? JSON.parse(storedFilters) : [];
3911
- const updatedStoredFilters = [...allRecentFilters, filter].slice(-10);
3912
- data.store.set(key, JSON.stringify(updatedStoredFilters));
3913
- const parent = this._parentVariable;
3914
- const existingFilter = parent.state.filters.find((f) => f.key === filter.key && !Boolean(f.nonApplicable));
3915
- if (existingFilter && !Boolean(existingFilter.nonApplicable)) {
3916
- this.setState({ recentFilters: updatedStoredFilters.slice(-3) });
3917
- }
3918
- }
3919
- /**
3920
- * Get the current filters from the parent variable
3921
- */
3922
- getParentFilters() {
3923
- return this._parentVariable.state.filters;
3924
- }
3925
- /**
3926
- * Add a filter to the parent variable
3927
- */
3928
- addFilterToParent(filter) {
3929
- const parent = this._parentVariable;
3930
- parent.updateFilters([...parent.state.filters, filter]);
3931
- }
3932
- }
3933
- AdHocFiltersRecommendations.Component = AdHocFiltersRecommendationsRenderer;
3934
- function AdHocFiltersRecommendationsRenderer({ model }) {
3935
- const { recentFilters, recommendedFilters } = model.useState();
3936
- const { filters } = model.parent.useState();
3937
- const recentDrilldowns = recentFilters == null ? void 0 : recentFilters.map((filter) => ({
3938
- label: `${filter.key} ${filter.operator} ${filter.value}`,
3939
- onClick: () => {
3940
- model.addFilterToParent(filter);
3941
- }
3942
- }));
3943
- const recommendedDrilldowns = recommendedFilters == null ? void 0 : recommendedFilters.map((filter) => ({
3944
- label: `${filter.key} ${filter.operator} ${filter.value}`,
3945
- onClick: () => {
3946
- const exists = filters.some((f) => f.key === filter.key && f.value === filter.value);
3947
- if (!exists) {
3948
- model.addFilterToParent(filter);
3949
- }
3950
- }
3951
- }));
3952
- return /* @__PURE__ */ React__default.default.createElement(DrilldownRecommendations, { recentDrilldowns, recommendedDrilldowns });
3953
- }
3954
-
3955
- const getRecentGroupingKey = (datasourceUid) => `grafana.grouping.recent.${datasourceUid != null ? datasourceUid : "default"}`;
3956
- class GroupByRecommendations extends SceneObjectBase {
3957
- constructor(parent) {
3958
- super({});
3959
- this._scopedVars = { __sceneObject: wrapInSafeSerializableSceneObject(this) };
3960
- this._activationHandler = () => {
3961
- const json = data.store.get(this._getStorageKey());
3962
- const storedGroupings = json ? JSON.parse(json) : [];
3963
- if (storedGroupings.length > 0) {
3964
- this._verifyRecentGroupingsApplicability(storedGroupings);
3965
- } else {
3966
- this.setState({ recentGrouping: [] });
3967
- }
3968
- this._fetchRecommendedDrilldowns();
3969
- const scopesVariable = sceneGraph.lookupVariable(SCOPES_VARIABLE_NAME, this);
3970
- let scopesSubscription;
3971
- if (scopesVariable instanceof ScopesVariable) {
3972
- scopesSubscription = scopesVariable.subscribeToState((newState, prevState) => {
3973
- if (newState.scopes !== prevState.scopes) {
3974
- const json2 = data.store.get(this._getStorageKey());
3975
- const storedGroupings2 = json2 ? JSON.parse(json2) : [];
3976
- if (storedGroupings2.length > 0) {
3977
- this._verifyRecentGroupingsApplicability(storedGroupings2);
3978
- }
3979
- }
3980
- });
3981
- }
3982
- return () => {
3983
- scopesSubscription == null ? void 0 : scopesSubscription.unsubscribe();
3984
- };
3985
- };
3986
- this._parentVariable = parent;
3987
- this.addActivationHandler(this._activationHandler);
3988
- }
3989
- /**
3990
- * Get the parent variable
3991
- */
3992
- get parent() {
3993
- return this._parentVariable;
3994
- }
3995
- _getStorageKey() {
3996
- var _a;
3997
- return getRecentGroupingKey((_a = this._parentVariable.state.datasource) == null ? void 0 : _a.uid);
3998
- }
3999
- async _fetchRecommendedDrilldowns() {
4000
- const parent = this._parentVariable;
4001
- const ds = await getDataSource(parent.state.datasource, this._scopedVars);
4002
- if (!ds || !ds.getRecommendedDrilldowns) {
4003
- return;
4004
- }
4005
- const queries = getQueriesForVariables(parent);
4006
- const timeRange = sceneGraph.getTimeRange(this).state.value;
4007
- const scopes = sceneGraph.getScopes(this);
4008
- const groupByKeys = Array.isArray(parent.state.value) ? parent.state.value.map((v) => String(v)) : parent.state.value ? [String(parent.state.value)] : [];
4009
- const enrichedRequest = getEnrichedDataRequest(this);
4010
- const dashboardUid = enrichedRequest == null ? void 0 : enrichedRequest.dashboardUID;
4011
- try {
4012
- const recommendedDrilldowns = await ds.getRecommendedDrilldowns({
4013
- timeRange,
4014
- dashboardUid,
4015
- queries,
4016
- groupByKeys,
4017
- scopes,
4018
- userId: runtime.config.bootData.user.id
4019
- });
4020
- if (recommendedDrilldowns == null ? void 0 : recommendedDrilldowns.groupByKeys) {
4021
- this.setState({
4022
- recommendedGrouping: recommendedDrilldowns.groupByKeys.map((key) => ({ value: key, text: key }))
4023
- });
4024
- }
4025
- } catch (error) {
4026
- console.error("Failed to fetch recommended drilldowns:", error);
4027
- }
4028
- }
4029
- async _verifyRecentGroupingsApplicability(storedGroupings) {
4030
- const queries = getQueriesForVariables(this._parentVariable);
4031
- const keys = storedGroupings.map((g) => String(g.value));
4032
- const response = await this._getGroupByApplicabilityForQueries(keys, queries);
4033
- if (!response) {
4034
- this.setState({ recentGrouping: storedGroupings.slice(-3) });
4035
- return;
4036
- }
4037
- const applicabilityMap = /* @__PURE__ */ new Map();
4038
- response.forEach((item) => {
4039
- applicabilityMap.set(item.key, item.applicable !== false);
4040
- });
4041
- const applicableGroupings = storedGroupings.filter((g) => {
4042
- const isApplicable = applicabilityMap.get(String(g.value));
4043
- return isApplicable === void 0 || isApplicable === true;
4044
- }).slice(-3);
4045
- this.setState({ recentGrouping: applicableGroupings });
4046
- }
4047
- async _getGroupByApplicabilityForQueries(value, queries) {
4048
- const parent = this._parentVariable;
4049
- const ds = await getDataSource(parent.state.datasource, this._scopedVars);
4050
- if (!ds || !ds.getDrilldownsApplicability) {
4051
- return;
4052
- }
4053
- const timeRange = sceneGraph.getTimeRange(this).state.value;
4054
- return await ds.getDrilldownsApplicability({
4055
- groupByKeys: Array.isArray(value) ? value.map((v) => String(v)) : value ? [String(value)] : [],
4056
- queries,
4057
- timeRange,
4058
- scopes: sceneGraph.getScopes(this),
4059
- ...getEnrichedFiltersRequest(this)
4060
- });
4061
- }
4062
- /**
4063
- * Stores recent groupings in localStorage and updates state.
4064
- * Should be called by the parent variable when a grouping is added/updated.
4065
- */
4066
- storeRecentGrouping(applicableValues) {
4067
- if (applicableValues.length === 0) {
4068
- return;
4069
- }
4070
- const key = this._getStorageKey();
4071
- const storedGroupings = data.store.get(key);
4072
- const allRecentGroupings = storedGroupings ? JSON.parse(storedGroupings) : [];
4073
- const existingWithoutApplicableValues = allRecentGroupings.filter(
4074
- (grouping) => !applicableValues.includes(String(grouping.value))
4075
- );
4076
- const updatedStoredGroupings = [
4077
- ...existingWithoutApplicableValues,
4078
- ...applicableValues.map((value) => ({ value, text: value }))
4079
- ];
4080
- const limitedStoredGroupings = updatedStoredGroupings.slice(-10);
4081
- data.store.set(key, JSON.stringify(limitedStoredGroupings));
4082
- this.setState({ recentGrouping: limitedStoredGroupings.slice(-3) });
4083
- }
4084
- /**
4085
- * Get the current values from the parent variable
4086
- */
4087
- getParentValues() {
4088
- const parent = this._parentVariable;
4089
- const value = lodash.isArray(parent.state.value) ? parent.state.value : [parent.state.value];
4090
- const text = lodash.isArray(parent.state.text) ? parent.state.text.map(String) : [String(parent.state.text)];
4091
- return { value, text };
4092
- }
4093
- /**
4094
- * Add a grouping value to the parent variable
4095
- */
4096
- addValueToParent(newValue, newText) {
4097
- const parent = this._parentVariable;
4098
- const { value, text } = this.getParentValues();
4099
- if (value.includes(newValue)) {
4100
- return;
4101
- }
4102
- parent.changeValueTo(
4103
- [...value.filter((v) => v !== ""), newValue],
4104
- [...text.filter((t) => t !== ""), newText != null ? newText : String(newValue)],
4105
- true
4106
- );
4107
- }
4108
- }
4109
- GroupByRecommendations.Component = GroupByRecommendationsRenderer;
4110
- function GroupByRecommendationsRenderer({ model }) {
4111
- const { recentGrouping, recommendedGrouping } = model.useState();
4112
- const recentDrilldowns = recentGrouping == null ? void 0 : recentGrouping.map((groupBy) => ({
4113
- label: `${groupBy.value}`,
4114
- onClick: () => {
4115
- var _a;
4116
- model.addValueToParent(groupBy.value, (_a = groupBy.text) != null ? _a : String(groupBy.value));
4117
- }
4118
- }));
4119
- const recommendedDrilldowns = recommendedGrouping == null ? void 0 : recommendedGrouping.map((groupBy) => ({
4120
- label: `${groupBy.value}`,
4121
- onClick: () => {
4122
- var _a;
4123
- model.addValueToParent(groupBy.value, (_a = groupBy.text) != null ? _a : String(groupBy.value));
4124
- }
4125
- }));
4126
- return /* @__PURE__ */ React__default.default.createElement(DrilldownRecommendations, { recentDrilldowns, recommendedDrilldowns });
4127
- }
4128
-
4129
3617
  class GroupByVariable extends MultiValueVariable {
4130
3618
  constructor(initialState) {
4131
3619
  super({
@@ -4151,11 +3639,6 @@ class GroupByVariable extends MultiValueVariable {
4151
3639
  this.setState({ restorable: true });
4152
3640
  }
4153
3641
  }
4154
- if (this.state.drilldownRecommendationsEnabled && !this.state._valueRecommendations) {
4155
- const valueRecommendations = new GroupByRecommendations(this);
4156
- this.setState({ _valueRecommendations: valueRecommendations });
4157
- valueRecommendations.activate();
4158
- }
4159
3642
  return () => {
4160
3643
  if (this.state.defaultValue) {
4161
3644
  this.restoreDefaultValues();
@@ -4271,7 +3754,7 @@ class GroupByVariable extends MultiValueVariable {
4271
3754
  }
4272
3755
  getApplicableKeys() {
4273
3756
  const { value, keysApplicability } = this.state;
4274
- const valueArray = lodash.isArray(value) ? value.map(String) : value ? [String(value)] : [];
3757
+ const valueArray = lodash.isArray(value) ? value : value ? [value] : [];
4275
3758
  if (!keysApplicability || keysApplicability.length === 0) {
4276
3759
  return valueArray;
4277
3760
  }
@@ -4330,17 +3813,6 @@ class GroupByVariable extends MultiValueVariable {
4330
3813
  }
4331
3814
  this.changeValueTo(this.state.defaultValue.value, this.state.defaultValue.text, true);
4332
3815
  }
4333
- async _verifyApplicabilityAndStoreRecentGrouping() {
4334
- await this._verifyApplicability();
4335
- if (!this.state.drilldownRecommendationsEnabled || !this.state._valueRecommendations) {
4336
- return;
4337
- }
4338
- const applicableValues = this.getApplicableKeys();
4339
- if (applicableValues.length === 0) {
4340
- return;
4341
- }
4342
- this.state._valueRecommendations.storeRecentGrouping(applicableValues);
4343
- }
4344
3816
  /**
4345
3817
  * Allows clearing the value of the variable to an empty value. Overrides default behavior of a MultiValueVariable
4346
3818
  */
@@ -4361,11 +3833,8 @@ function GroupByVariableRenderer({ model }) {
4361
3833
  includeAll,
4362
3834
  allowCustomValue = true,
4363
3835
  defaultValue,
4364
- keysApplicability,
4365
- _valueRecommendations,
4366
- drilldownRecommendationsEnabled
3836
+ keysApplicability
4367
3837
  } = model.useState();
4368
- const styles = ui.useStyles2(getStyles$j);
4369
3838
  const values = React.useMemo(() => {
4370
3839
  const arrayValue = lodash.isArray(value) ? value : [value];
4371
3840
  const arrayText = lodash.isArray(text) ? text : [text];
@@ -4404,7 +3873,7 @@ function GroupByVariableRenderer({ model }) {
4404
3873
  () => handleOptionGroups(optionSearcher(inputValue).map(toSelectableValue$1)),
4405
3874
  [optionSearcher, inputValue]
4406
3875
  );
4407
- const select = isMulti ? /* @__PURE__ */ React__default.default.createElement(
3876
+ return isMulti ? /* @__PURE__ */ React__default.default.createElement(
4408
3877
  ui.MultiSelect,
4409
3878
  {
4410
3879
  "aria-label": i18n.t(
@@ -4418,7 +3887,6 @@ function GroupByVariableRenderer({ model }) {
4418
3887
  "Group by label"
4419
3888
  ),
4420
3889
  width: "auto",
4421
- className: css.cx(drilldownRecommendationsEnabled && styles.selectStylesInWrapper),
4422
3890
  allowCustomValue,
4423
3891
  inputValue,
4424
3892
  value: uncommittedValue,
@@ -4452,7 +3920,7 @@ function GroupByVariableRenderer({ model }) {
4452
3920
  if (restorable !== model.state.restorable) {
4453
3921
  model.setState({ restorable });
4454
3922
  }
4455
- model._verifyApplicabilityAndStoreRecentGrouping();
3923
+ model._verifyApplicability();
4456
3924
  },
4457
3925
  onChange: (newValue, action) => {
4458
3926
  if (action.action === "clear" && noValueOnClear) {
@@ -4488,7 +3956,6 @@ function GroupByVariableRenderer({ model }) {
4488
3956
  "Group by label"
4489
3957
  ),
4490
3958
  width: "auto",
4491
- className: css.cx(drilldownRecommendationsEnabled && styles.selectStylesInWrapper),
4492
3959
  inputValue,
4493
3960
  value: uncommittedValue && uncommittedValue.length > 0 ? uncommittedValue : null,
4494
3961
  allowCustomValue,
@@ -4533,10 +4000,6 @@ function GroupByVariableRenderer({ model }) {
4533
4000
  }
4534
4001
  }
4535
4002
  );
4536
- if (!drilldownRecommendationsEnabled || !_valueRecommendations) {
4537
- return select;
4538
- }
4539
- 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);
4540
4003
  }
4541
4004
  const filterNoOp$1 = () => true;
4542
4005
  function WideMenu(props) {
@@ -4553,31 +4016,6 @@ function toSelectableValue$1(input) {
4553
4016
  }
4554
4017
  return result;
4555
4018
  }
4556
- const getStyles$j = (theme) => ({
4557
- wrapper: css.css({
4558
- display: "flex"
4559
- }),
4560
- selectStylesInWrapper: css.css({
4561
- borderTopLeftRadius: 0,
4562
- borderBottomLeftRadius: 0,
4563
- border: `1px solid ${theme.colors.border.strong}`,
4564
- borderLeft: "none"
4565
- }),
4566
- recommendations: css.css({
4567
- display: "flex",
4568
- alignItems: "center",
4569
- paddingInline: theme.spacing(0.5),
4570
- borderTop: `1px solid ${theme.colors.border.strong}`,
4571
- borderBottom: `1px solid ${theme.colors.border.strong}`,
4572
- backgroundColor: theme.components.input.background,
4573
- "& button": {
4574
- borderRadius: 0,
4575
- height: "100%",
4576
- margin: 0,
4577
- paddingInline: theme.spacing(0.5)
4578
- }
4579
- })
4580
- });
4581
4019
 
4582
4020
  function VizPanelSeriesLimit({ data, showAll, seriesLimit, onShowAllSeries }) {
4583
4021
  const styles = ui.useStyles2(getStyles$i);
@@ -7223,6 +6661,9 @@ const generatePlaceholder = (filter, filterInputType, isMultiValueEdit, isAlways
7223
6661
  }
7224
6662
  return ((_a = filter.valueLabels) == null ? void 0 : _a[0]) || "";
7225
6663
  }
6664
+ if (isAlwaysWip && filterInputType === "operator") {
6665
+ return "";
6666
+ }
7226
6667
  return filter[filterInputType] && !isAlwaysWip ? `${filter[filterInputType]}` : inputPlaceholder || INPUT_PLACEHOLDER_DEFAULT;
7227
6668
  };
7228
6669
  const populateInputValueOnInputTypeSwitch = ({
@@ -7411,7 +6852,8 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({
7411
6852
  isAlwaysWip,
7412
6853
  handleChangeViewMode,
7413
6854
  focusOnWipInputRef,
7414
- populateInputOnEdit
6855
+ populateInputOnEdit,
6856
+ onInputClick
7415
6857
  }, parentRef) {
7416
6858
  var _a, _b, _c;
7417
6859
  const [open, setOpen] = React.useState(false);
@@ -7894,6 +7336,7 @@ const AdHocCombobox = React.forwardRef(function AdHocCombobox2({
7894
7336
  className: css.cx(styles.inputStyle, { [styles.loadingInputPadding]: !optionsLoading }),
7895
7337
  onClick: (event) => {
7896
7338
  event.stopPropagation();
7339
+ onInputClick == null ? void 0 : onInputClick();
7897
7340
  setOpen(true);
7898
7341
  },
7899
7342
  onFocus: () => {
@@ -8352,53 +7795,102 @@ const getStyles$a = (theme) => ({
8352
7795
  ...getNonApplicablePillStyles(theme)
8353
7796
  });
8354
7797
 
8355
- const AdHocFiltersAlwaysWipCombobox = React.forwardRef(function AdHocFiltersAlwaysWipCombobox2({ controller }, parentRef) {
7798
+ const AdHocFiltersAlwaysWipCombobox = React.forwardRef(function AdHocFiltersAlwaysWipCombobox2({ controller, onInputClick }, parentRef) {
8356
7799
  const { wip } = controller.useState();
8357
7800
  React.useLayoutEffect(() => {
8358
7801
  if (!wip) {
8359
7802
  controller.addWip();
8360
7803
  }
8361
7804
  }, [wip]);
8362
- return /* @__PURE__ */ React__default.default.createElement(AdHocCombobox, { controller, filter: wip, isAlwaysWip: true, ref: parentRef });
7805
+ return /* @__PURE__ */ React__default.default.createElement(AdHocCombobox, { controller, filter: wip, isAlwaysWip: true, ref: parentRef, onInputClick });
8363
7806
  });
8364
7807
 
7808
+ const MAX_VISIBLE_FILTERS = 4;
8365
7809
  const AdHocFiltersComboboxRenderer = React.memo(function AdHocFiltersComboboxRenderer2({ controller }) {
8366
- const { originFilters, filters, readOnly, valueRecommendations, drilldownRecommendationsEnabled } = controller.useState();
7810
+ var _a;
7811
+ const { originFilters, filters, readOnly, collapsible } = controller.useState();
8367
7812
  const styles = ui.useStyles2(getStyles$9);
7813
+ const theme = ui.useTheme2();
7814
+ const [collapsed, setCollapsed] = React.useState(true);
7815
+ const [wrapperRef, { height: wrapperHeight }] = reactUse.useMeasure();
7816
+ const clearAll = () => {
7817
+ controller.clearAll();
7818
+ };
8368
7819
  const focusOnWipInputRef = React.useRef();
7820
+ const singleLineThreshold = theme.spacing.gridSize * 5;
7821
+ const isMultiLine = collapsible && wrapperHeight > singleLineThreshold;
7822
+ const handleCollapseToggle = (event) => {
7823
+ event.stopPropagation();
7824
+ if (collapsible) {
7825
+ setCollapsed(true);
7826
+ }
7827
+ };
7828
+ const handleExpand = () => {
7829
+ var _a2, _b;
7830
+ if (!collapsible) {
7831
+ (_a2 = focusOnWipInputRef.current) == null ? void 0 : _a2.call(focusOnWipInputRef);
7832
+ return;
7833
+ }
7834
+ if (collapsed) {
7835
+ setCollapsed(false);
7836
+ } else {
7837
+ (_b = focusOnWipInputRef.current) == null ? void 0 : _b.call(focusOnWipInputRef);
7838
+ }
7839
+ };
7840
+ const visibleOriginFilters = (_a = originFilters == null ? void 0 : originFilters.filter((f) => f.origin)) != null ? _a : [];
7841
+ const visibleFilters = filters.filter((f) => !f.hidden);
7842
+ const allFilters = [...visibleOriginFilters, ...visibleFilters];
7843
+ const totalFiltersCount = allFilters.length;
7844
+ const shouldCollapse = collapsible && collapsed && totalFiltersCount > 0;
7845
+ const filtersToRender = shouldCollapse ? allFilters.slice(0, MAX_VISIBLE_FILTERS) : allFilters;
7846
+ React.useEffect(() => {
7847
+ if (collapsible && totalFiltersCount === 0 && collapsed) {
7848
+ setCollapsed(false);
7849
+ }
7850
+ }, [collapsible, totalFiltersCount, collapsed]);
7851
+ const showCollapseButton = collapsible && isMultiLine && !collapsed;
8369
7852
  return /* @__PURE__ */ React__default.default.createElement(
8370
7853
  "div",
8371
7854
  {
8372
- className: css.cx(styles.comboboxWrapper, { [styles.comboboxFocusOutline]: !readOnly }),
8373
- onClick: () => {
8374
- var _a;
8375
- (_a = focusOnWipInputRef.current) == null ? void 0 : _a.call(focusOnWipInputRef);
8376
- }
7855
+ ref: wrapperRef,
7856
+ className: css.cx(styles.comboboxWrapper, {
7857
+ [styles.comboboxFocusOutline]: !readOnly,
7858
+ [styles.collapsed]: shouldCollapse,
7859
+ [styles.clickableCollapsed]: shouldCollapse
7860
+ }),
7861
+ onClick: handleExpand
8377
7862
  },
8378
7863
  /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "filter", className: styles.filterIcon, size: "lg" }),
8379
- drilldownRecommendationsEnabled && valueRecommendations && /* @__PURE__ */ React__default.default.createElement(valueRecommendations.Component, { model: valueRecommendations }),
8380
- originFilters == null ? void 0 : originFilters.map(
8381
- (filter, index) => filter.origin ? /* @__PURE__ */ React__default.default.createElement(
8382
- AdHocFilterPill,
8383
- {
8384
- key: `${index}-${filter.key}`,
8385
- filter,
8386
- controller,
8387
- focusOnWipInputRef: focusOnWipInputRef.current
8388
- }
8389
- ) : null
8390
- ),
8391
- filters.filter((filter) => !filter.hidden).map((filter, index) => /* @__PURE__ */ React__default.default.createElement(
7864
+ filtersToRender.map((filter, index) => /* @__PURE__ */ React__default.default.createElement(
8392
7865
  AdHocFilterPill,
8393
7866
  {
8394
- key: `${index}-${filter.key}`,
7867
+ key: `${filter.origin ? "origin-" : ""}${index}-${filter.key}`,
8395
7868
  filter,
8396
7869
  controller,
8397
7870
  readOnly: readOnly || filter.readOnly,
8398
7871
  focusOnWipInputRef: focusOnWipInputRef.current
8399
7872
  }
8400
7873
  )),
8401
- !readOnly ? /* @__PURE__ */ React__default.default.createElement(AdHocFiltersAlwaysWipCombobox, { controller, ref: focusOnWipInputRef }) : null
7874
+ shouldCollapse && totalFiltersCount > MAX_VISIBLE_FILTERS && /* @__PURE__ */ React__default.default.createElement("span", { className: styles.moreIndicator }, i18n.t("grafana-scenes.variables.adhoc-filters-combobox-renderer.more-filters", "+{{count}} more", {
7875
+ count: totalFiltersCount - MAX_VISIBLE_FILTERS
7876
+ })),
7877
+ !readOnly && !shouldCollapse ? /* @__PURE__ */ React__default.default.createElement(AdHocFiltersAlwaysWipCombobox, { controller, ref: focusOnWipInputRef }) : null,
7878
+ showCollapseButton && /* @__PURE__ */ React__default.default.createElement(
7879
+ ui.Button,
7880
+ {
7881
+ className: styles.collapseButton,
7882
+ fill: "text",
7883
+ onClick: handleCollapseToggle,
7884
+ "aria-label": i18n.t(
7885
+ "grafana-scenes.variables.adhoc-filters-combobox-renderer.collapse-filters",
7886
+ "Collapse filters"
7887
+ ),
7888
+ "aria-expanded": !collapsed
7889
+ },
7890
+ i18n.t("grafana-scenes.variables.adhoc-filters-combobox-renderer.collapse", "Collapse"),
7891
+ /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "angle-up", size: "md" })
7892
+ ),
7893
+ /* @__PURE__ */ React__default.default.createElement("div", { className: styles.clearAllButton }, /* @__PURE__ */ React__default.default.createElement(ui.Icon, { name: "times", size: "md", onClick: clearAll }))
8402
7894
  );
8403
7895
  });
8404
7896
  const getStyles$9 = (theme) => ({
@@ -8430,6 +7922,42 @@ const getStyles$9 = (theme) => ({
8430
7922
  filterIcon: css.css({
8431
7923
  color: theme.colors.text.secondary,
8432
7924
  alignSelf: "center"
7925
+ }),
7926
+ collapsed: css.css({
7927
+ flexWrap: "nowrap",
7928
+ overflow: "hidden"
7929
+ }),
7930
+ clickableCollapsed: css.css({
7931
+ cursor: "pointer",
7932
+ "&:hover": {
7933
+ borderColor: theme.colors.border.medium
7934
+ }
7935
+ }),
7936
+ moreIndicator: css.css({
7937
+ color: theme.colors.text.secondary,
7938
+ whiteSpace: "nowrap",
7939
+ ...theme.typography.bodySmall,
7940
+ fontStyle: "italic",
7941
+ marginLeft: theme.spacing(0.5)
7942
+ }),
7943
+ collapseButton: css.css({
7944
+ marginLeft: "auto",
7945
+ color: theme.colors.text.secondary,
7946
+ padding: 0,
7947
+ fontSize: theme.typography.bodySmall.fontSize,
7948
+ border: "none",
7949
+ "&:hover": {
7950
+ background: "transparent",
7951
+ color: theme.colors.text.primary
7952
+ }
7953
+ }),
7954
+ clearAllButton: css.css({
7955
+ fontSize: theme.typography.bodySmall.fontSize,
7956
+ cursor: "pointer",
7957
+ color: theme.colors.text.secondary,
7958
+ "&:hover": {
7959
+ color: theme.colors.text.primary
7960
+ }
8433
7961
  })
8434
7962
  });
8435
7963
 
@@ -8534,8 +8062,7 @@ class AdHocFiltersVariableController {
8534
8062
  supportsMultiValueOperators: state.supportsMultiValueOperators,
8535
8063
  onAddCustomValue: state.onAddCustomValue,
8536
8064
  wip: state._wip,
8537
- valueRecommendations: state._valueRecommendations,
8538
- drilldownRecommendationsEnabled: state.drilldownRecommendationsEnabled
8065
+ collapsible: state.collapsible
8539
8066
  };
8540
8067
  }
8541
8068
  async getKeys(currentKey) {
@@ -8550,9 +8077,6 @@ class AdHocFiltersVariableController {
8550
8077
  updateFilter(filter, update) {
8551
8078
  this.model._updateFilter(filter, update);
8552
8079
  }
8553
- updateFilters(filters, options) {
8554
- this.model.updateFilters(filters, options);
8555
- }
8556
8080
  updateToMatchAll(filter) {
8557
8081
  this.model.updateToMatchAll(filter);
8558
8082
  }
@@ -8571,6 +8095,9 @@ class AdHocFiltersVariableController {
8571
8095
  restoreOriginalFilter(filter) {
8572
8096
  this.model.restoreOriginalFilter(filter);
8573
8097
  }
8098
+ clearAll() {
8099
+ this.model.clearAll();
8100
+ }
8574
8101
  startProfile(name) {
8575
8102
  const queryController = getQueryController(this.model);
8576
8103
  queryController == null ? void 0 : queryController.startProfile(name);
@@ -8660,11 +8187,6 @@ class AdHocFiltersVariable extends SceneObjectBase {
8660
8187
  this._debouncedVerifyApplicability = lodash.debounce(this._verifyApplicability, 100);
8661
8188
  this._activationHandler = () => {
8662
8189
  this._debouncedVerifyApplicability();
8663
- if (this.state.drilldownRecommendationsEnabled && !this.state._valueRecommendations) {
8664
- const valueRecommendations = new AdHocFiltersRecommendations(this);
8665
- this.setState({ _valueRecommendations: valueRecommendations });
8666
- valueRecommendations.activate();
8667
- }
8668
8190
  return () => {
8669
8191
  var _a;
8670
8192
  (_a = this.state.originFilters) == null ? void 0 : _a.forEach((filter) => {
@@ -8734,13 +8256,6 @@ class AdHocFiltersVariable extends SceneObjectBase {
8734
8256
  this._prevScopes = scopes;
8735
8257
  this._debouncedVerifyApplicability();
8736
8258
  }
8737
- async verifyApplicabilityAndStoreRecentFilter(update) {
8738
- await this._verifyApplicability();
8739
- if (!this.state.drilldownRecommendationsEnabled || !this.state._valueRecommendations) {
8740
- return;
8741
- }
8742
- this.state._valueRecommendations.storeRecentFilter(update);
8743
- }
8744
8259
  setState(update) {
8745
8260
  var _a, _b;
8746
8261
  let filterExpressionChanged = false;
@@ -8799,6 +8314,18 @@ class AdHocFiltersVariable extends SceneObjectBase {
8799
8314
  this._updateFilter(filter, original);
8800
8315
  }
8801
8316
  }
8317
+ /**
8318
+ * Clear all user-added filters and restore origin filters to their original values.
8319
+ */
8320
+ clearAll() {
8321
+ var _a;
8322
+ (_a = this.state.originFilters) == null ? void 0 : _a.forEach((filter) => {
8323
+ if (filter.restorable) {
8324
+ this.restoreOriginalFilter(filter);
8325
+ }
8326
+ });
8327
+ this.setState({ filters: [] });
8328
+ }
8802
8329
  getValue(fieldPath) {
8803
8330
  if (fieldPath === ORIGIN_FILTERS_KEY) {
8804
8331
  const originFilters = this.state.originFilters;
@@ -8832,11 +8359,8 @@ class AdHocFiltersVariable extends SceneObjectBase {
8832
8359
  }
8833
8360
  if (filter === _wip) {
8834
8361
  if ("value" in update && update["value"] !== "") {
8835
- this.setState({
8836
- filters: [...filters, { ..._wip, ...update }],
8837
- _wip: void 0
8838
- });
8839
- this.verifyApplicabilityAndStoreRecentFilter({ ..._wip, ...update });
8362
+ this.setState({ filters: [...filters, { ..._wip, ...update }], _wip: void 0 });
8363
+ this._debouncedVerifyApplicability();
8840
8364
  } else {
8841
8365
  this.setState({ _wip: { ...filter, ...update } });
8842
8366
  }
@@ -8846,12 +8370,6 @@ class AdHocFiltersVariable extends SceneObjectBase {
8846
8370
  return f === filter ? { ...f, ...update } : f;
8847
8371
  });
8848
8372
  this.setState({ filters: updatedFilters });
8849
- if (this.state.drilldownRecommendationsEnabled && this.state._valueRecommendations) {
8850
- this.state._valueRecommendations.storeRecentFilter({
8851
- ...filter,
8852
- ...update
8853
- });
8854
- }
8855
8373
  }
8856
8374
  updateToMatchAll(filter) {
8857
8375
  this._updateFilter(filter, {
@@ -9042,12 +8560,11 @@ class AdHocFiltersVariable extends SceneObjectBase {
9042
8560
  let scopes = sceneGraph.getScopes(this);
9043
8561
  if (filter.origin === "scope") {
9044
8562
  scopes = scopes == null ? void 0 : scopes.map((scope) => {
9045
- var _a2;
9046
8563
  return {
9047
8564
  ...scope,
9048
8565
  spec: {
9049
8566
  ...scope.spec,
9050
- filters: (_a2 = scope.spec.filters) == null ? void 0 : _a2.filter((f) => f.key !== filter.key)
8567
+ filters: scope.spec.filters.filter((f) => f.key !== filter.key)
9051
8568
  }
9052
8569
  };
9053
8570
  });
@@ -10536,6 +10053,91 @@ function containsSearchFilter(query) {
10536
10053
  return str.indexOf(SEARCH_FILTER_VARIABLE) > -1;
10537
10054
  }
10538
10055
 
10056
+ class ScopesVariable extends SceneObjectBase {
10057
+ constructor(state) {
10058
+ super({
10059
+ skipUrlSync: true,
10060
+ loading: true,
10061
+ scopes: [],
10062
+ ...state,
10063
+ type: "system",
10064
+ name: SCOPES_VARIABLE_NAME,
10065
+ hide: schema.VariableHide.hideVariable
10066
+ });
10067
+ this._renderBeforeActivation = true;
10068
+ // Special options that enables variables to be hidden but still render to access react contexts
10069
+ this.UNSAFE_renderAsHidden = true;
10070
+ }
10071
+ /**
10072
+ * Temporary simple implementation to stringify the scopes.
10073
+ */
10074
+ getValue() {
10075
+ var _a;
10076
+ const scopes = (_a = this.state.scopes) != null ? _a : [];
10077
+ return new ScopesVariableFormatter(scopes.map((scope) => scope.metadata.name));
10078
+ }
10079
+ getScopes() {
10080
+ return this.state.scopes;
10081
+ }
10082
+ /**
10083
+ * This method is used to keep the context up to date with the scopes context received from React
10084
+ * 1) Subscribes to ScopesContext state changes and synchronizes it with the variable state
10085
+ * 2) Handles enable / disabling of scopes based on variable enable option.
10086
+ */
10087
+ setContext(context) {
10088
+ if (!context) {
10089
+ return;
10090
+ }
10091
+ this._context = context;
10092
+ const oldState = context.state;
10093
+ if (this.state.enable != null) {
10094
+ context.setEnabled(this.state.enable);
10095
+ }
10096
+ const sub = context.stateObservable.subscribe((state) => {
10097
+ this.updateStateFromContext(state);
10098
+ });
10099
+ return () => {
10100
+ sub.unsubscribe();
10101
+ if (this.state.enable != null) {
10102
+ context.setEnabled(oldState.enabled);
10103
+ }
10104
+ };
10105
+ }
10106
+ updateStateFromContext(state) {
10107
+ const loading = state.value.length === 0 ? false : state.loading;
10108
+ const oldScopes = this.state.scopes.map((scope) => scope.metadata.name);
10109
+ const newScopes = state.value.map((scope) => scope.metadata.name);
10110
+ const scopesHaveChanged = !lodash.isEqual(oldScopes, newScopes);
10111
+ if (!loading && (scopesHaveChanged || newScopes.length === 0)) {
10112
+ const queryController = getQueryController(this);
10113
+ queryController == null ? void 0 : queryController.startProfile(SCOPES_CHANGED_INTERACTION);
10114
+ this.setState({ scopes: state.value, loading });
10115
+ this.publishEvent(new SceneVariableValueChangedEvent(this), true);
10116
+ } else {
10117
+ this.setState({ loading });
10118
+ }
10119
+ }
10120
+ }
10121
+ ScopesVariable.Component = ScopesVariableRenderer;
10122
+ function ScopesVariableRenderer({ model }) {
10123
+ const context = React.useContext(runtime.ScopesContext);
10124
+ React.useEffect(() => {
10125
+ return model.setContext(context);
10126
+ }, [context, model]);
10127
+ return null;
10128
+ }
10129
+ class ScopesVariableFormatter {
10130
+ constructor(_value) {
10131
+ this._value = _value;
10132
+ }
10133
+ formatter(formatNameOrFn) {
10134
+ if (formatNameOrFn === schema.VariableFormatID.QueryParam) {
10135
+ return this._value.map((scope) => `scope=${encodeURIComponent(scope)}`).join("&");
10136
+ }
10137
+ return this._value.join(", ");
10138
+ }
10139
+ }
10140
+
10539
10141
  function getVariables(sceneObject) {
10540
10142
  var _a;
10541
10143
  return (_a = getClosest(sceneObject, (s) => s.state.$variables)) != null ? _a : EmptyVariableSet;
@@ -16852,7 +16454,7 @@ function __variableDynamicImportRuntime0__(path) {
16852
16454
  switch (path) {
16853
16455
  case '../locales/cs-CZ/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-DPdlSPjz.js'); });
16854
16456
  case '../locales/de-DE/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-BHIE4ld0.js'); });
16855
- case '../locales/en-US/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-C9F_2hih.js'); });
16457
+ case '../locales/en-US/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-CwGWCTcQ.js'); });
16856
16458
  case '../locales/es-ES/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-D4tq59Dc.js'); });
16857
16459
  case '../locales/fr-FR/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-Ce77KCbO.js'); });
16858
16460
  case '../locales/hu-HU/grafana-scenes.json': return Promise.resolve().then(function () { return require('./grafana-scenes-DMYCnFop.js'); });
@@ -16997,7 +16599,6 @@ exports.dataLayers = index;
16997
16599
  exports.escapeUrlPipeDelimiters = escapeUrlPipeDelimiters;
16998
16600
  exports.formatRegistry = formatRegistry;
16999
16601
  exports.getExploreURL = getExploreURL;
17000
- exports.getQueriesForVariables = getQueriesForVariables;
17001
16602
  exports.isCustomVariableValue = isCustomVariableValue;
17002
16603
  exports.isDataLayer = isDataLayer;
17003
16604
  exports.isDataRequestEnricher = isDataRequestEnricher;