@perses-dev/plugin-system 0.34.0 → 0.36.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 (40) hide show
  1. package/dist/cjs/components/CalculationSelector/CalculationSelector.js +1 -6
  2. package/dist/cjs/components/LegendOptionsEditor/LegendOptionsEditor.js +77 -10
  3. package/dist/cjs/model/legend.js +28 -0
  4. package/dist/cjs/runtime/TimeRangeProvider/TimeRangeProvider.js +11 -11
  5. package/dist/cjs/runtime/TimeRangeProvider/query-params.js +80 -1
  6. package/dist/cjs/runtime/template-variables.js +0 -2
  7. package/dist/cjs/runtime/time-series-queries.js +5 -2
  8. package/dist/cjs/stories/shared-utils/decorators/WithTimeRange.js +1 -0
  9. package/dist/components/CalculationSelector/CalculationSelector.d.ts.map +1 -1
  10. package/dist/components/CalculationSelector/CalculationSelector.js +2 -7
  11. package/dist/components/CalculationSelector/CalculationSelector.js.map +1 -1
  12. package/dist/components/LegendOptionsEditor/LegendOptionsEditor.d.ts.map +1 -1
  13. package/dist/components/LegendOptionsEditor/LegendOptionsEditor.js +81 -14
  14. package/dist/components/LegendOptionsEditor/LegendOptionsEditor.js.map +1 -1
  15. package/dist/model/legend.d.ts +9 -2
  16. package/dist/model/legend.d.ts.map +1 -1
  17. package/dist/model/legend.js +33 -1
  18. package/dist/model/legend.js.map +1 -1
  19. package/dist/model/time-series-queries.d.ts +1 -0
  20. package/dist/model/time-series-queries.d.ts.map +1 -1
  21. package/dist/model/time-series-queries.js.map +1 -1
  22. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts +5 -1
  23. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts.map +1 -1
  24. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js +12 -12
  25. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js.map +1 -1
  26. package/dist/runtime/TimeRangeProvider/query-params.d.ts +12 -0
  27. package/dist/runtime/TimeRangeProvider/query-params.d.ts.map +1 -1
  28. package/dist/runtime/TimeRangeProvider/query-params.js +82 -1
  29. package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
  30. package/dist/runtime/template-variables.d.ts +0 -1
  31. package/dist/runtime/template-variables.d.ts.map +1 -1
  32. package/dist/runtime/template-variables.js +0 -1
  33. package/dist/runtime/template-variables.js.map +1 -1
  34. package/dist/runtime/time-series-queries.d.ts +1 -1
  35. package/dist/runtime/time-series-queries.d.ts.map +1 -1
  36. package/dist/runtime/time-series-queries.js +5 -2
  37. package/dist/runtime/time-series-queries.js.map +1 -1
  38. package/dist/stories/shared-utils/decorators/WithTimeRange.js +1 -0
  39. package/dist/stories/shared-utils/decorators/WithTimeRange.js.map +1 -1
  40. package/package.json +4 -4
@@ -19,7 +19,6 @@ Object.defineProperty(exports, "CalculationSelector", {
19
19
  get: ()=>CalculationSelector
20
20
  });
21
21
  const _jsxRuntime = require("react/jsx-runtime");
22
- const _material = require("@mui/material");
23
22
  const _components = require("@perses-dev/components");
24
23
  const _core = require("@perses-dev/core");
25
24
  const CALC_OPTIONS = Object.entries(_core.CALCULATIONS_CONFIG).map(([id, config])=>{
@@ -35,16 +34,12 @@ function CalculationSelector({ value , onChange }) {
35
34
  const calcConfig = _core.CALCULATIONS_CONFIG[value];
36
35
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.OptionsEditorControl, {
37
36
  label: "Calculation",
38
- control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Autocomplete, {
37
+ control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.SettingsAutocomplete, {
39
38
  value: {
40
39
  ...calcConfig,
41
40
  id: value
42
41
  },
43
42
  options: CALC_OPTIONS,
44
- isOptionEqualToValue: (option, value)=>option.id === value.id,
45
- renderInput: (params)=>/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.TextField, {
46
- ...params
47
- }),
48
43
  onChange: handleCalculationChange,
49
44
  disableClearable: true
50
45
  })
@@ -35,6 +35,18 @@ const MODE_OPTIONS = Object.entries(_model.LEGEND_MODE_CONFIG).map(([id, config]
35
35
  ...config
36
36
  };
37
37
  });
38
+ const SIZE_OPTIONS = Object.entries(_model.LEGEND_SIZE_CONFIG).map(([id, config])=>{
39
+ return {
40
+ id: id,
41
+ ...config
42
+ };
43
+ });
44
+ const VALUE_OPTIONS = Object.entries(_model.LEGEND_VALUE_CONFIG).map(([id, config])=>{
45
+ return {
46
+ id: id,
47
+ ...config
48
+ };
49
+ });
38
50
  function LegendOptionsEditor({ value , onChange }) {
39
51
  const handleLegendShowChange = (_, checked)=>{
40
52
  // legend is hidden when legend obj is undefined
@@ -56,11 +68,40 @@ function LegendOptionsEditor({ value , onChange }) {
56
68
  mode: newValue.id
57
69
  });
58
70
  };
71
+ const handleLegendSizeChange = (_, newValue)=>{
72
+ onChange({
73
+ ...value,
74
+ position: currentPosition,
75
+ size: newValue.id
76
+ });
77
+ };
78
+ const handleLegendValueChange = (_, newValue)=>{
79
+ onChange({
80
+ ...value,
81
+ position: currentPosition,
82
+ values: newValue.map((value)=>{
83
+ return value.id;
84
+ })
85
+ });
86
+ };
59
87
  const isValidLegend = (0, _model.validateLegendSpec)(value);
60
88
  const currentPosition = (0, _core.getLegendPosition)(value === null || value === void 0 ? void 0 : value.position);
61
89
  const legendPositionConfig = _model.LEGEND_POSITIONS_CONFIG[currentPosition];
62
90
  const currentMode = (0, _core.getLegendMode)(value === null || value === void 0 ? void 0 : value.mode);
63
91
  const legendModeConfig = _model.LEGEND_MODE_CONFIG[currentMode];
92
+ const currentSize = (0, _core.getLegendSize)(value === null || value === void 0 ? void 0 : value.size);
93
+ const legendSizeConfig = _model.LEGEND_SIZE_CONFIG[currentSize];
94
+ const currentValues = (value === null || value === void 0 ? void 0 : value.values) || [];
95
+ const legendValuesConfig = currentValues.reduce((result, item)=>{
96
+ const config = _model.LEGEND_VALUE_CONFIG[item];
97
+ if (config) {
98
+ result.push({
99
+ ...config,
100
+ id: item
101
+ });
102
+ }
103
+ return result;
104
+ }, []);
64
105
  return /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
65
106
  children: [
66
107
  !isValidLegend && /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.ErrorAlert, {
@@ -78,16 +119,12 @@ function LegendOptionsEditor({ value , onChange }) {
78
119
  }),
79
120
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.OptionsEditorControl, {
80
121
  label: "Position",
81
- control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Autocomplete, {
122
+ control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.SettingsAutocomplete, {
82
123
  value: {
83
124
  ...legendPositionConfig,
84
125
  id: currentPosition
85
126
  },
86
127
  options: POSITION_OPTIONS,
87
- isOptionEqualToValue: (option, value)=>option.id === value.id,
88
- renderInput: (params)=>/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.TextField, {
89
- ...params
90
- }),
91
128
  onChange: handleLegendPositionChange,
92
129
  disabled: value === undefined,
93
130
  disableClearable: true
@@ -95,20 +132,50 @@ function LegendOptionsEditor({ value , onChange }) {
95
132
  }),
96
133
  /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.OptionsEditorControl, {
97
134
  label: "Mode",
98
- control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Autocomplete, {
135
+ control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.SettingsAutocomplete, {
99
136
  value: {
100
137
  ...legendModeConfig,
101
138
  id: currentMode
102
139
  },
103
140
  options: MODE_OPTIONS,
104
- isOptionEqualToValue: (option, value)=>option.id === value.id,
105
- renderInput: (params)=>/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.TextField, {
106
- ...params
107
- }),
108
141
  onChange: handleLegendModeChange,
109
142
  disabled: value === undefined,
110
143
  disableClearable: true
111
144
  })
145
+ }),
146
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.OptionsEditorControl, {
147
+ label: "Size",
148
+ control: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.SettingsAutocomplete, {
149
+ value: {
150
+ ...legendSizeConfig,
151
+ id: currentSize
152
+ },
153
+ options: SIZE_OPTIONS,
154
+ onChange: handleLegendSizeChange,
155
+ // TODO: enable sizes for list mode when we normalize the layout of
156
+ // lists to more closely match tables.
157
+ disabled: value === undefined || currentMode !== 'Table',
158
+ disableClearable: true
159
+ })
160
+ }),
161
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.OptionsEditorControl, {
162
+ label: "Values",
163
+ control: // For some reason, the inferred option type doesn't always seem to work
164
+ // quite right when `multiple` is true. Explicitly setting the generics
165
+ // to work around this.
166
+ /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.SettingsAutocomplete, {
167
+ multiple: true,
168
+ disableCloseOnSelect: true,
169
+ disableClearable: true,
170
+ value: legendValuesConfig,
171
+ options: VALUE_OPTIONS,
172
+ onChange: handleLegendValueChange,
173
+ disabled: value === undefined || currentMode !== 'Table',
174
+ limitTags: 1,
175
+ ChipProps: {
176
+ size: 'small'
177
+ }
178
+ })
112
179
  })
113
180
  ]
114
181
  });
@@ -21,11 +21,24 @@ function _export(target, all) {
21
21
  });
22
22
  }
23
23
  _export(exports, {
24
+ legendValues: ()=>legendValues,
24
25
  LEGEND_POSITIONS_CONFIG: ()=>LEGEND_POSITIONS_CONFIG,
25
26
  LEGEND_MODE_CONFIG: ()=>LEGEND_MODE_CONFIG,
27
+ LEGEND_SIZE_CONFIG: ()=>LEGEND_SIZE_CONFIG,
28
+ LEGEND_VALUE_CONFIG: ()=>LEGEND_VALUE_CONFIG,
26
29
  validateLegendSpec: ()=>validateLegendSpec
27
30
  });
28
31
  const _core = require("@perses-dev/core");
32
+ const legendValues = [
33
+ 'Mean',
34
+ 'First',
35
+ 'FirstNumber',
36
+ 'Last',
37
+ 'LastNumber',
38
+ 'Min',
39
+ 'Max',
40
+ 'Sum'
41
+ ];
29
42
  const LEGEND_POSITIONS_CONFIG = {
30
43
  Bottom: {
31
44
  label: 'Bottom'
@@ -42,6 +55,18 @@ const LEGEND_MODE_CONFIG = {
42
55
  label: 'Table'
43
56
  }
44
57
  };
58
+ const LEGEND_SIZE_CONFIG = {
59
+ Small: {
60
+ label: 'Small'
61
+ },
62
+ Medium: {
63
+ label: 'Medium'
64
+ }
65
+ };
66
+ const LEGEND_VALUE_CONFIG = legendValues.reduce((config, value)=>{
67
+ config[value] = _core.CALCULATIONS_CONFIG[value];
68
+ return config;
69
+ }, {});
45
70
  function validateLegendSpec(legend) {
46
71
  if (legend === undefined) {
47
72
  // undefined is valid since this is how legend is hidden by default
@@ -53,5 +78,8 @@ function validateLegendSpec(legend) {
53
78
  if (legend.mode && !(0, _core.isValidLegendMode)(legend.mode)) {
54
79
  return false;
55
80
  }
81
+ if (legend.size && !(0, _core.isValidLegendSize)(legend.size)) {
82
+ return false;
83
+ }
56
84
  return true;
57
85
  }
@@ -78,18 +78,12 @@ function useTimeRangeContext() {
78
78
  return ctx;
79
79
  }
80
80
  function useTimeRange() {
81
- const { timeRange , absoluteTimeRange , setTimeRange , refresh , refreshKey } = useTimeRangeContext();
82
- return {
83
- timeRange,
84
- absoluteTimeRange,
85
- setTimeRange,
86
- refresh,
87
- refreshKey
88
- };
81
+ return useTimeRangeContext();
89
82
  }
90
83
  function TimeRangeProvider(props) {
91
- const { initialTimeRange , enabledURLParams , children } = props;
84
+ const { initialTimeRange , initialRefreshInterval , enabledURLParams , children } = props;
92
85
  const { timeRange , setTimeRange } = (0, _queryParams.useSetTimeRangeParams)(initialTimeRange, enabledURLParams);
86
+ const { refreshInterval , setRefreshInterval , refreshIntervalInMs } = (0, _queryParams.useSetRefreshIntervalParams)(initialRefreshInterval, enabledURLParams);
93
87
  const [refreshKey, setRefreshKey] = (0, _react.useState)(0);
94
88
  const refresh = (0, _react.useCallback)(()=>{
95
89
  setRefreshKey(refreshKey + 1);
@@ -103,13 +97,19 @@ function TimeRangeProvider(props) {
103
97
  setTimeRange,
104
98
  absoluteTimeRange,
105
99
  refresh,
106
- refreshKey: `${absoluteTimeRange.start}:${absoluteTimeRange.end}:${refreshKey}`
100
+ refreshKey: `${absoluteTimeRange.start}:${absoluteTimeRange.end}:${refreshInterval}:${refreshKey}`,
101
+ refreshInterval,
102
+ refreshIntervalInMs,
103
+ setRefreshInterval
107
104
  };
108
105
  }, [
109
106
  timeRange,
110
107
  setTimeRange,
111
108
  refresh,
112
- refreshKey
109
+ refreshKey,
110
+ refreshInterval,
111
+ refreshIntervalInMs,
112
+ setRefreshInterval
113
113
  ]);
114
114
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(TimeRangeContext.Provider, {
115
115
  value: ctx,
@@ -25,8 +25,11 @@ _export(exports, {
25
25
  decodeTimeRangeValue: ()=>decodeTimeRangeValue,
26
26
  TimeRangeParam: ()=>TimeRangeParam,
27
27
  timeRangeQueryConfig: ()=>timeRangeQueryConfig,
28
+ refreshIntervalQueryConfig: ()=>refreshIntervalQueryConfig,
28
29
  useInitialTimeRange: ()=>useInitialTimeRange,
29
- useSetTimeRangeParams: ()=>useSetTimeRangeParams
30
+ useSetTimeRangeParams: ()=>useSetTimeRangeParams,
31
+ useInitialRefreshInterval: ()=>useInitialRefreshInterval,
32
+ useSetRefreshIntervalParams: ()=>useSetRefreshIntervalParams
30
33
  });
31
34
  const _react = require("react");
32
35
  const _useQueryParams = require("use-query-params");
@@ -78,6 +81,9 @@ const timeRangeQueryConfig = {
78
81
  start: TimeRangeParam,
79
82
  end: TimeRangeParam
80
83
  };
84
+ const refreshIntervalQueryConfig = {
85
+ refresh: TimeRangeParam
86
+ };
81
87
  function useInitialTimeRange(dashboardDuration) {
82
88
  const [query] = (0, _useQueryParams.useQueryParams)(timeRangeQueryConfig, {
83
89
  updateType: 'replaceIn'
@@ -159,3 +165,76 @@ function useSetTimeRangeParams(initialTimeRange, enabledURLParams = true) {
159
165
  setTimeRange: setTimeRange
160
166
  };
161
167
  }
168
+ function useInitialRefreshInterval(dashboardDuration) {
169
+ const [query] = (0, _useQueryParams.useQueryParams)(refreshIntervalQueryConfig, {
170
+ updateType: 'replaceIn'
171
+ });
172
+ const { refresh } = query;
173
+ return (0, _react.useMemo)(()=>{
174
+ let initialTimeRange = dashboardDuration;
175
+ if (!refresh) {
176
+ return initialTimeRange;
177
+ }
178
+ const startStr = refresh.toString();
179
+ if ((0, _core.isDurationString)(startStr)) {
180
+ initialTimeRange = startStr;
181
+ }
182
+ return initialTimeRange;
183
+ }, [
184
+ dashboardDuration,
185
+ refresh
186
+ ]);
187
+ }
188
+ function getRefreshIntervalInMs(refreshInterval) {
189
+ let refreshIntervalInMs = 0;
190
+ if (refreshInterval) {
191
+ const refreshIntervalDuration = (0, _core.parseDurationString)(refreshInterval);
192
+ if (refreshIntervalDuration && refreshIntervalDuration.seconds) {
193
+ refreshIntervalInMs = (refreshIntervalDuration === null || refreshIntervalDuration === void 0 ? void 0 : refreshIntervalDuration.seconds) * 1000;
194
+ }
195
+ }
196
+ return refreshIntervalInMs;
197
+ }
198
+ function useSetRefreshIntervalParams(initialRefreshInterval, enabledURLParams = true) {
199
+ const [query, setQuery] = (0, _useQueryParams.useQueryParams)(refreshIntervalQueryConfig, {
200
+ updateType: 'replaceIn'
201
+ });
202
+ // determine whether initial param had previously been populated to fix back btn
203
+ const [paramsLoaded, setParamsLoaded] = (0, _react.useState)(false);
204
+ // optional fallback when app does not want query string as source of truth
205
+ // this occurs when enabledURLParams is set to false on TimeRangeProvider
206
+ const [refreshIntervalState, setRefreshIntervalState] = (0, _react.useState)(initialRefreshInterval);
207
+ const { refresh } = query;
208
+ (0, _react.useEffect)(()=>{
209
+ // when dashboard loaded with no params, default to dashboard duration
210
+ if (enabledURLParams && !paramsLoaded && !refresh) {
211
+ setQuery({
212
+ refresh: initialRefreshInterval
213
+ });
214
+ setParamsLoaded(true);
215
+ }
216
+ }, [
217
+ initialRefreshInterval,
218
+ enabledURLParams,
219
+ paramsLoaded,
220
+ refresh,
221
+ setQuery
222
+ ]);
223
+ const setRefreshInterval = (0, _react.useCallback)((refresh)=>setQuery({
224
+ refresh
225
+ }), [
226
+ setQuery
227
+ ]);
228
+ if (!enabledURLParams) {
229
+ return {
230
+ refreshInterval: refreshIntervalState,
231
+ setRefreshInterval: setRefreshIntervalState,
232
+ refreshIntervalInMs: getRefreshIntervalInMs(refreshIntervalState)
233
+ };
234
+ }
235
+ return {
236
+ refreshInterval: initialRefreshInterval,
237
+ setRefreshInterval: setRefreshInterval,
238
+ refreshIntervalInMs: getRefreshIntervalInMs(initialRefreshInterval)
239
+ };
240
+ }
@@ -21,14 +21,12 @@ function _export(target, all) {
21
21
  });
22
22
  }
23
23
  _export(exports, {
24
- DEFAULT_ALL_VALUE: ()=>DEFAULT_ALL_VALUE,
25
24
  TemplateVariableContext: ()=>TemplateVariableContext,
26
25
  useTemplateVariableValues: ()=>useTemplateVariableValues,
27
26
  useReplaceVariablesInString: ()=>useReplaceVariablesInString
28
27
  });
29
28
  const _react = require("react");
30
29
  const _utils = require("../utils");
31
- const DEFAULT_ALL_VALUE = '$__all';
32
30
  const TemplateVariableContext = (0, _react.createContext)(undefined);
33
31
  function useTemplateVariableContext() {
34
32
  const ctx = (0, _react.useContext)(TemplateVariableContext);
@@ -84,6 +84,7 @@ const useTimeSeriesQuery = (definition, options)=>{
84
84
  return (0, _reactQuery.useQuery)({
85
85
  enabled: queryEnabled,
86
86
  queryKey: queryKey,
87
+ refetchInterval: context.refreshIntervalInMs > 0 ? context.refreshIntervalInMs : false,
87
88
  queryFn: ()=>{
88
89
  // The 'enabled' option should prevent this from happening, but make TypeScript happy by checking
89
90
  if (plugin === undefined) {
@@ -116,6 +117,7 @@ function useTimeSeriesQueries(definitions, options) {
116
117
  return {
117
118
  enabled: queryEnabled,
118
119
  queryKey: queryKey,
120
+ refetchInterval: context.refreshIntervalInMs > 0 ? context.refreshIntervalInMs : false,
119
121
  queryFn: async ()=>{
120
122
  // Keep options out of query key so we don't re-run queries because suggested step changes
121
123
  const ctx = {
@@ -133,14 +135,15 @@ function useTimeSeriesQueries(definitions, options) {
133
135
  /**
134
136
  * Build the time series query context object from data available at runtime
135
137
  */ function useTimeSeriesQueryContext() {
136
- const { absoluteTimeRange , refreshKey } = (0, _timeRangeProvider.useTimeRange)();
138
+ const { absoluteTimeRange , refreshKey , refreshIntervalInMs } = (0, _timeRangeProvider.useTimeRange)();
137
139
  const variableState = (0, _templateVariables.useTemplateVariableValues)();
138
140
  const datasourceStore = (0, _datasources.useDatasourceStore)();
139
141
  return {
140
142
  timeRange: absoluteTimeRange,
141
143
  variableState,
142
144
  datasourceStore,
143
- refreshKey
145
+ refreshKey,
146
+ refreshIntervalInMs: refreshIntervalInMs
144
147
  };
145
148
  }
146
149
  function useActiveTimeSeriesQueries() {
@@ -29,6 +29,7 @@ const WithTimeRange = (Story, context)=>{
29
29
  const parameter = isWithTimeRangeParameter(initParameter) ? initParameter : undefined;
30
30
  const props = parameter === null || parameter === void 0 ? void 0 : parameter.props;
31
31
  return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_pluginSystem.TimeRangeProvider, {
32
+ initialRefreshInterval: "0s",
32
33
  initialTimeRange: {
33
34
  pastDuration: '1h'
34
35
  },
@@ -1 +1 @@
1
- {"version":3,"file":"CalculationSelector.d.ts","sourceRoot":"","sources":["../../../src/components/CalculationSelector/CalculationSelector.tsx"],"names":[],"mappings":";AAeA,OAAO,EAA0C,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAU3F,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;CAC3C;AAED,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,wBAAwB,eAyBhF"}
1
+ {"version":3,"file":"CalculationSelector.d.ts","sourceRoot":"","sources":["../../../src/components/CalculationSelector/CalculationSelector.tsx"],"names":[],"mappings":";AAcA,OAAO,EAA0C,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAU3F,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,eAAe,CAAC;IACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;CAC3C;AAED,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,wBAAwB,eAuBhF"}
@@ -11,8 +11,7 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { jsx as _jsx } from "react/jsx-runtime";
14
- import { TextField, Autocomplete } from '@mui/material';
15
- import { OptionsEditorControl } from '@perses-dev/components';
14
+ import { OptionsEditorControl, SettingsAutocomplete } from '@perses-dev/components';
16
15
  import { CALCULATIONS_CONFIG } from '@perses-dev/core';
17
16
  const CALC_OPTIONS = Object.entries(CALCULATIONS_CONFIG).map(([id, config])=>{
18
17
  return {
@@ -27,16 +26,12 @@ export function CalculationSelector({ value , onChange }) {
27
26
  const calcConfig = CALCULATIONS_CONFIG[value];
28
27
  return /*#__PURE__*/ _jsx(OptionsEditorControl, {
29
28
  label: "Calculation",
30
- control: /*#__PURE__*/ _jsx(Autocomplete, {
29
+ control: /*#__PURE__*/ _jsx(SettingsAutocomplete, {
31
30
  value: {
32
31
  ...calcConfig,
33
32
  id: value
34
33
  },
35
34
  options: CALC_OPTIONS,
36
- isOptionEqualToValue: (option, value)=>option.id === value.id,
37
- renderInput: (params)=>/*#__PURE__*/ _jsx(TextField, {
38
- ...params
39
- }),
40
35
  onChange: handleCalculationChange,
41
36
  disableClearable: true
42
37
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/CalculationSelector/CalculationSelector.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { TextField, Autocomplete } from '@mui/material';\nimport { OptionsEditorControl } from '@perses-dev/components';\nimport { CALCULATIONS_CONFIG, CalculationConfig, CalculationType } from '@perses-dev/core';\n\ntype AutocompleteCalculationOption = CalculationConfig & { id: CalculationType };\nconst CALC_OPTIONS: AutocompleteCalculationOption[] = Object.entries(CALCULATIONS_CONFIG).map(([id, config]) => {\n return {\n id: id as CalculationType,\n ...config,\n };\n});\n\nexport interface CalculationSelectorProps {\n value: CalculationType;\n onChange: (unit: CalculationType) => void;\n}\n\nexport function CalculationSelector({ value, onChange }: CalculationSelectorProps) {\n const handleCalculationChange = (_: unknown, newValue: AutocompleteCalculationOption) => {\n onChange(newValue.id);\n };\n\n const calcConfig = CALCULATIONS_CONFIG[value];\n\n return (\n <OptionsEditorControl\n label=\"Calculation\"\n control={\n <Autocomplete\n value={{\n ...calcConfig,\n id: value,\n }}\n options={CALC_OPTIONS}\n isOptionEqualToValue={(option, value) => option.id === value.id}\n renderInput={(params) => <TextField {...params} />}\n onChange={handleCalculationChange}\n disableClearable\n ></Autocomplete>\n }\n />\n );\n}\n"],"names":["TextField","Autocomplete","OptionsEditorControl","CALCULATIONS_CONFIG","CALC_OPTIONS","Object","entries","map","id","config","CalculationSelector","value","onChange","handleCalculationChange","_","newValue","calcConfig","label","control","options","isOptionEqualToValue","option","renderInput","params","disableClearable"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,SAAS,EAAEC,YAAY,QAAQ,eAAe,CAAC;AACxD,SAASC,oBAAoB,QAAQ,wBAAwB,CAAC;AAC9D,SAASC,mBAAmB,QAA4C,kBAAkB,CAAC;AAG3F,MAAMC,YAAY,GAAoCC,MAAM,CAACC,OAAO,CAACH,mBAAmB,CAAC,CAACI,GAAG,CAAC,CAAC,CAACC,EAAE,EAAEC,MAAM,CAAC,GAAK;IAC9G,OAAO;QACLD,EAAE,EAAEA,EAAE;QACN,GAAGC,MAAM;KACV,CAAC;AACJ,CAAC,CAAC,AAAC;AAOH,OAAO,SAASC,mBAAmB,CAAC,EAAEC,KAAK,CAAA,EAAEC,QAAQ,CAAA,EAA4B,EAAE;IACjF,MAAMC,uBAAuB,GAAG,CAACC,CAAU,EAAEC,QAAuC,GAAK;QACvFH,QAAQ,CAACG,QAAQ,CAACP,EAAE,CAAC,CAAC;IACxB,CAAC,AAAC;IAEF,MAAMQ,UAAU,GAAGb,mBAAmB,CAACQ,KAAK,CAAC,AAAC;IAE9C,qBACE,KAACT,oBAAoB;QACnBe,KAAK,EAAC,aAAa;QACnBC,OAAO,gBACL,KAACjB,YAAY;YACXU,KAAK,EAAE;gBACL,GAAGK,UAAU;gBACbR,EAAE,EAAEG,KAAK;aACV;YACDQ,OAAO,EAAEf,YAAY;YACrBgB,oBAAoB,EAAE,CAACC,MAAM,EAAEV,KAAK,GAAKU,MAAM,CAACb,EAAE,KAAKG,KAAK,CAACH,EAAE;YAC/Dc,WAAW,EAAE,CAACC,MAAM,iBAAK,KAACvB,SAAS;oBAAE,GAAGuB,MAAM;kBAAI;YAClDX,QAAQ,EAAEC,uBAAuB;YACjCW,gBAAgB;UACF;MAElB,CACF;AACJ,CAAC"}
1
+ {"version":3,"sources":["../../../src/components/CalculationSelector/CalculationSelector.tsx"],"sourcesContent":["// Copyright 2023 The Perses Authors\n// Licensed under the Apache License, Version 2.0 (the \"License\");\n// you may not use this file except in compliance with the License.\n// You may obtain a copy of the License at\n//\n// http://www.apache.org/licenses/LICENSE-2.0\n//\n// Unless required by applicable law or agreed to in writing, software\n// distributed under the License is distributed on an \"AS IS\" BASIS,\n// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n// See the License for the specific language governing permissions and\n// limitations under the License.\n\nimport { OptionsEditorControl, SettingsAutocomplete } from '@perses-dev/components';\nimport { CALCULATIONS_CONFIG, CalculationConfig, CalculationType } from '@perses-dev/core';\n\ntype AutocompleteCalculationOption = CalculationConfig & { id: CalculationType };\nconst CALC_OPTIONS: AutocompleteCalculationOption[] = Object.entries(CALCULATIONS_CONFIG).map(([id, config]) => {\n return {\n id: id as CalculationType,\n ...config,\n };\n});\n\nexport interface CalculationSelectorProps {\n value: CalculationType;\n onChange: (unit: CalculationType) => void;\n}\n\nexport function CalculationSelector({ value, onChange }: CalculationSelectorProps) {\n const handleCalculationChange = (_: unknown, newValue: AutocompleteCalculationOption) => {\n onChange(newValue.id);\n };\n\n const calcConfig = CALCULATIONS_CONFIG[value];\n\n return (\n <OptionsEditorControl\n label=\"Calculation\"\n control={\n <SettingsAutocomplete\n value={{\n ...calcConfig,\n id: value,\n }}\n options={CALC_OPTIONS}\n onChange={handleCalculationChange}\n disableClearable\n ></SettingsAutocomplete>\n }\n />\n );\n}\n"],"names":["OptionsEditorControl","SettingsAutocomplete","CALCULATIONS_CONFIG","CALC_OPTIONS","Object","entries","map","id","config","CalculationSelector","value","onChange","handleCalculationChange","_","newValue","calcConfig","label","control","options","disableClearable"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,oBAAoB,EAAEC,oBAAoB,QAAQ,wBAAwB,CAAC;AACpF,SAASC,mBAAmB,QAA4C,kBAAkB,CAAC;AAG3F,MAAMC,YAAY,GAAoCC,MAAM,CAACC,OAAO,CAACH,mBAAmB,CAAC,CAACI,GAAG,CAAC,CAAC,CAACC,EAAE,EAAEC,MAAM,CAAC,GAAK;IAC9G,OAAO;QACLD,EAAE,EAAEA,EAAE;QACN,GAAGC,MAAM;KACV,CAAC;AACJ,CAAC,CAAC,AAAC;AAOH,OAAO,SAASC,mBAAmB,CAAC,EAAEC,KAAK,CAAA,EAAEC,QAAQ,CAAA,EAA4B,EAAE;IACjF,MAAMC,uBAAuB,GAAG,CAACC,CAAU,EAAEC,QAAuC,GAAK;QACvFH,QAAQ,CAACG,QAAQ,CAACP,EAAE,CAAC,CAAC;IACxB,CAAC,AAAC;IAEF,MAAMQ,UAAU,GAAGb,mBAAmB,CAACQ,KAAK,CAAC,AAAC;IAE9C,qBACE,KAACV,oBAAoB;QACnBgB,KAAK,EAAC,aAAa;QACnBC,OAAO,gBACL,KAAChB,oBAAoB;YACnBS,KAAK,EAAE;gBACL,GAAGK,UAAU;gBACbR,EAAE,EAAEG,KAAK;aACV;YACDQ,OAAO,EAAEf,YAAY;YACrBQ,QAAQ,EAAEC,uBAAuB;YACjCO,gBAAgB;UACM;MAE1B,CACF;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"LegendOptionsEditor.d.ts","sourceRoot":"","sources":["../../../src/components/LegendOptionsEditor/LegendOptionsEditor.tsx"],"names":[],"mappings":";AAgBA,OAAO,EAGL,iBAAiB,EAGlB,MAAM,aAAa,CAAC;AAoBrB,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAChD;AAED,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,wBAAwB,eAwEhF"}
1
+ {"version":3,"file":"LegendOptionsEditor.d.ts","sourceRoot":"","sources":["../../../src/components/LegendOptionsEditor/LegendOptionsEditor.tsx"],"names":[],"mappings":";AAgBA,OAAO,EAGL,iBAAiB,EAMlB,MAAM,aAAa,CAAC;AAqCrB,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B,QAAQ,EAAE,CAAC,MAAM,CAAC,EAAE,iBAAiB,KAAK,IAAI,CAAC;CAChD;AAED,wBAAgB,mBAAmB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,wBAAwB,eAwIhF"}
@@ -11,10 +11,10 @@
11
11
  // See the License for the specific language governing permissions and
12
12
  // limitations under the License.
13
13
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
- import { Autocomplete, Switch, TextField } from '@mui/material';
15
- import { DEFAULT_LEGEND, getLegendMode, getLegendPosition } from '@perses-dev/core';
16
- import { ErrorAlert, OptionsEditorControl } from '@perses-dev/components';
17
- import { LEGEND_MODE_CONFIG, LEGEND_POSITIONS_CONFIG, validateLegendSpec } from '../../model';
14
+ import { Switch } from '@mui/material';
15
+ import { DEFAULT_LEGEND, getLegendMode, getLegendPosition, getLegendSize } from '@perses-dev/core';
16
+ import { ErrorAlert, OptionsEditorControl, SettingsAutocomplete } from '@perses-dev/components';
17
+ import { LEGEND_MODE_CONFIG, LEGEND_POSITIONS_CONFIG, validateLegendSpec, LEGEND_VALUE_CONFIG, LEGEND_SIZE_CONFIG } from '../../model';
18
18
  const POSITION_OPTIONS = Object.entries(LEGEND_POSITIONS_CONFIG).map(([id, config])=>{
19
19
  return {
20
20
  id: id,
@@ -27,6 +27,18 @@ const MODE_OPTIONS = Object.entries(LEGEND_MODE_CONFIG).map(([id, config])=>{
27
27
  ...config
28
28
  };
29
29
  });
30
+ const SIZE_OPTIONS = Object.entries(LEGEND_SIZE_CONFIG).map(([id, config])=>{
31
+ return {
32
+ id: id,
33
+ ...config
34
+ };
35
+ });
36
+ const VALUE_OPTIONS = Object.entries(LEGEND_VALUE_CONFIG).map(([id, config])=>{
37
+ return {
38
+ id: id,
39
+ ...config
40
+ };
41
+ });
30
42
  export function LegendOptionsEditor({ value , onChange }) {
31
43
  const handleLegendShowChange = (_, checked)=>{
32
44
  // legend is hidden when legend obj is undefined
@@ -48,11 +60,40 @@ export function LegendOptionsEditor({ value , onChange }) {
48
60
  mode: newValue.id
49
61
  });
50
62
  };
63
+ const handleLegendSizeChange = (_, newValue)=>{
64
+ onChange({
65
+ ...value,
66
+ position: currentPosition,
67
+ size: newValue.id
68
+ });
69
+ };
70
+ const handleLegendValueChange = (_, newValue)=>{
71
+ onChange({
72
+ ...value,
73
+ position: currentPosition,
74
+ values: newValue.map((value)=>{
75
+ return value.id;
76
+ })
77
+ });
78
+ };
51
79
  const isValidLegend = validateLegendSpec(value);
52
80
  const currentPosition = getLegendPosition(value === null || value === void 0 ? void 0 : value.position);
53
81
  const legendPositionConfig = LEGEND_POSITIONS_CONFIG[currentPosition];
54
82
  const currentMode = getLegendMode(value === null || value === void 0 ? void 0 : value.mode);
55
83
  const legendModeConfig = LEGEND_MODE_CONFIG[currentMode];
84
+ const currentSize = getLegendSize(value === null || value === void 0 ? void 0 : value.size);
85
+ const legendSizeConfig = LEGEND_SIZE_CONFIG[currentSize];
86
+ const currentValues = (value === null || value === void 0 ? void 0 : value.values) || [];
87
+ const legendValuesConfig = currentValues.reduce((result, item)=>{
88
+ const config = LEGEND_VALUE_CONFIG[item];
89
+ if (config) {
90
+ result.push({
91
+ ...config,
92
+ id: item
93
+ });
94
+ }
95
+ return result;
96
+ }, []);
56
97
  return /*#__PURE__*/ _jsxs(_Fragment, {
57
98
  children: [
58
99
  !isValidLegend && /*#__PURE__*/ _jsx(ErrorAlert, {
@@ -70,16 +111,12 @@ export function LegendOptionsEditor({ value , onChange }) {
70
111
  }),
71
112
  /*#__PURE__*/ _jsx(OptionsEditorControl, {
72
113
  label: "Position",
73
- control: /*#__PURE__*/ _jsx(Autocomplete, {
114
+ control: /*#__PURE__*/ _jsx(SettingsAutocomplete, {
74
115
  value: {
75
116
  ...legendPositionConfig,
76
117
  id: currentPosition
77
118
  },
78
119
  options: POSITION_OPTIONS,
79
- isOptionEqualToValue: (option, value)=>option.id === value.id,
80
- renderInput: (params)=>/*#__PURE__*/ _jsx(TextField, {
81
- ...params
82
- }),
83
120
  onChange: handleLegendPositionChange,
84
121
  disabled: value === undefined,
85
122
  disableClearable: true
@@ -87,20 +124,50 @@ export function LegendOptionsEditor({ value , onChange }) {
87
124
  }),
88
125
  /*#__PURE__*/ _jsx(OptionsEditorControl, {
89
126
  label: "Mode",
90
- control: /*#__PURE__*/ _jsx(Autocomplete, {
127
+ control: /*#__PURE__*/ _jsx(SettingsAutocomplete, {
91
128
  value: {
92
129
  ...legendModeConfig,
93
130
  id: currentMode
94
131
  },
95
132
  options: MODE_OPTIONS,
96
- isOptionEqualToValue: (option, value)=>option.id === value.id,
97
- renderInput: (params)=>/*#__PURE__*/ _jsx(TextField, {
98
- ...params
99
- }),
100
133
  onChange: handleLegendModeChange,
101
134
  disabled: value === undefined,
102
135
  disableClearable: true
103
136
  })
137
+ }),
138
+ /*#__PURE__*/ _jsx(OptionsEditorControl, {
139
+ label: "Size",
140
+ control: /*#__PURE__*/ _jsx(SettingsAutocomplete, {
141
+ value: {
142
+ ...legendSizeConfig,
143
+ id: currentSize
144
+ },
145
+ options: SIZE_OPTIONS,
146
+ onChange: handleLegendSizeChange,
147
+ // TODO: enable sizes for list mode when we normalize the layout of
148
+ // lists to more closely match tables.
149
+ disabled: value === undefined || currentMode !== 'Table',
150
+ disableClearable: true
151
+ })
152
+ }),
153
+ /*#__PURE__*/ _jsx(OptionsEditorControl, {
154
+ label: "Values",
155
+ control: // For some reason, the inferred option type doesn't always seem to work
156
+ // quite right when `multiple` is true. Explicitly setting the generics
157
+ // to work around this.
158
+ /*#__PURE__*/ _jsx(SettingsAutocomplete, {
159
+ multiple: true,
160
+ disableCloseOnSelect: true,
161
+ disableClearable: true,
162
+ value: legendValuesConfig,
163
+ options: VALUE_OPTIONS,
164
+ onChange: handleLegendValueChange,
165
+ disabled: value === undefined || currentMode !== 'Table',
166
+ limitTags: 1,
167
+ ChipProps: {
168
+ size: 'small'
169
+ }
170
+ })
104
171
  })
105
172
  ]
106
173
  });