@perses-dev/plugin-system 0.52.0-beta.5 → 0.52.0-rc.1
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/cjs/components/MultiQueryEditor/MultiQueryEditor.js +5 -2
- package/dist/cjs/components/MultiQueryEditor/QueryEditorContainer.js +13 -4
- package/dist/cjs/components/PanelSpecEditor/PanelSpecEditor.js +7 -5
- package/dist/cjs/components/PluginEditor/PluginEditor.js +16 -11
- package/dist/cjs/components/Variables/VariableEditorForm/VariableEditorForm.js +37 -87
- package/dist/cjs/components/Variables/VariableEditorForm/VariablePreview.js +12 -17
- package/dist/cjs/context/query-params.js +4 -4
- package/dist/cjs/runtime/TimeRangeProvider/TimeRangeProvider.js +6 -1
- package/dist/cjs/runtime/TimeRangeProvider/query-params.js +27 -27
- package/dist/cjs/test/utils.js +17 -8
- package/dist/cjs/utils/variables.js +109 -14
- package/dist/components/MultiQueryEditor/MultiQueryEditor.d.ts +3 -2
- package/dist/components/MultiQueryEditor/MultiQueryEditor.d.ts.map +1 -1
- package/dist/components/MultiQueryEditor/MultiQueryEditor.js +6 -3
- package/dist/components/MultiQueryEditor/MultiQueryEditor.js.map +1 -1
- package/dist/components/MultiQueryEditor/QueryEditorContainer.d.ts +3 -2
- package/dist/components/MultiQueryEditor/QueryEditorContainer.d.ts.map +1 -1
- package/dist/components/MultiQueryEditor/QueryEditorContainer.js +13 -4
- package/dist/components/MultiQueryEditor/QueryEditorContainer.js.map +1 -1
- package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts +3 -2
- package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts.map +1 -1
- package/dist/components/PanelSpecEditor/PanelSpecEditor.js +7 -5
- package/dist/components/PanelSpecEditor/PanelSpecEditor.js.map +1 -1
- package/dist/components/PluginEditor/PluginEditor.d.ts +3 -3
- package/dist/components/PluginEditor/PluginEditor.d.ts.map +1 -1
- package/dist/components/PluginEditor/PluginEditor.js +17 -12
- package/dist/components/PluginEditor/PluginEditor.js.map +1 -1
- package/dist/components/PluginEditor/plugin-editor-api.d.ts +4 -0
- package/dist/components/PluginEditor/plugin-editor-api.d.ts.map +1 -1
- package/dist/components/PluginEditor/plugin-editor-api.js.map +1 -1
- package/dist/components/TimeRangeControls/TimeRangeControls.js.map +1 -1
- package/dist/components/Variables/VariableEditorForm/VariableEditorForm.d.ts.map +1 -1
- package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js +38 -47
- package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js.map +1 -1
- package/dist/components/Variables/VariableEditorForm/VariablePreview.d.ts +0 -2
- package/dist/components/Variables/VariableEditorForm/VariablePreview.d.ts.map +1 -1
- package/dist/components/Variables/VariableEditorForm/VariablePreview.js +13 -18
- package/dist/components/Variables/VariableEditorForm/VariablePreview.js.map +1 -1
- package/dist/context/query-params.js +4 -4
- package/dist/context/query-params.js.map +1 -1
- package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts.map +1 -1
- package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js +6 -1
- package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js.map +1 -1
- package/dist/runtime/TimeRangeProvider/query-params.d.ts +7 -12
- package/dist/runtime/TimeRangeProvider/query-params.d.ts.map +1 -1
- package/dist/runtime/TimeRangeProvider/query-params.js +20 -23
- package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
- package/dist/test/utils.d.ts.map +1 -1
- package/dist/test/utils.js +17 -8
- package/dist/test/utils.js.map +1 -1
- package/dist/utils/variables.d.ts +24 -2
- package/dist/utils/variables.d.ts.map +1 -1
- package/dist/utils/variables.js +102 -14
- package/dist/utils/variables.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/PluginEditor/PluginEditor.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 { Box, Button } from '@mui/material';\nimport Reload from 'mdi-material-ui/Reload';\nimport { ErrorAlert, ErrorBoundary } from '@perses-dev/components';\nimport { ReactElement, useCallback, useMemo, useState } from 'react';\nimport { UnknownSpec } from '@perses-dev/core';\nimport { PluginKindSelect } from '../PluginKindSelect';\nimport { PluginSpecEditor } from '../PluginSpecEditor';\nimport { PluginEditorProps, usePluginEditor } from './plugin-editor-api';\n\n/**\n * A combination `PluginKindSelect` and `PluginSpecEditor` component. This is meant for editing the `plugin` property\n * that's common in our JSON specs where a user selects a plugin `kind` and then edits the `spec` via that plugin's\n * editor component. It takes care of transitioning from one plugin kind to another \"all at once\" so that when the\n * plugin's kind changes, the spec is also changed at the same time so those options editor components don't see a\n * previous plugin's spec state. If you just want this behavior, but in a different UI layout from this, try the\n * `usePluginEditor` hook that powers this component.\n */\nexport
|
|
1
|
+
{"version":3,"sources":["../../../src/components/PluginEditor/PluginEditor.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 { Box, Button } from '@mui/material';\nimport Reload from 'mdi-material-ui/Reload';\nimport { ErrorAlert, ErrorBoundary } from '@perses-dev/components';\nimport { forwardRef, ReactElement, useCallback, useImperativeHandle, useMemo, useState } from 'react';\nimport { UnknownSpec } from '@perses-dev/core';\nimport { PluginKindSelect } from '../PluginKindSelect';\nimport { PluginSpecEditor } from '../PluginSpecEditor';\nimport { PluginEditorProps, PluginEditorRef, usePluginEditor } from './plugin-editor-api';\n\n/**\n * A combination `PluginKindSelect` and `PluginSpecEditor` component. This is meant for editing the `plugin` property\n * that's common in our JSON specs where a user selects a plugin `kind` and then edits the `spec` via that plugin's\n * editor component. It takes care of transitioning from one plugin kind to another \"all at once\" so that when the\n * plugin's kind changes, the spec is also changed at the same time so those options editor components don't see a\n * previous plugin's spec state. If you just want this behavior, but in a different UI layout from this, try the\n * `usePluginEditor` hook that powers this component.\n */\n\nexport const PluginEditor = forwardRef<PluginEditorRef, PluginEditorProps>((props, ref): ReactElement => {\n const {\n value,\n withRunQueryButton = true,\n pluginTypes,\n pluginKindLabel,\n onChange: _,\n isReadonly,\n postExecuteRunQuery: refresh,\n ...others\n } = props;\n const { pendingSelection, isLoading, error, onSelectionChange, onSpecChange } = usePluginEditor(props);\n\n /* \n We could technically merge the watchedQuery, watchedOtherSpecs into a single watched-object,\n because at the end of the day, they are all specs.\n However, let's have them separated to keep the code simple and readable.\n Reason: Only Query string field is common between all of them. Other specs may be different\n Example: Legend, and MinSteps\n */\n const [watchedQuery, setWatchQuery] = useState<string>(value.spec['query'] as string);\n const [watchedOtherSpecs, setWatchOtherSpecs] = useState<UnknownSpec>(value.spec);\n\n const runQueryHandler = useCallback((): void => {\n onSpecChange({ ...value.spec, ...watchedOtherSpecs, query: watchedQuery });\n refresh?.();\n }, [value.spec, onSpecChange, watchedQuery, watchedOtherSpecs, refresh]);\n\n const queryHandlerSettings = useMemo(() => {\n return withRunQueryButton\n ? {\n runWithOnBlur: false,\n watchQueryChanges: (query: string): void => {\n setWatchQuery(query);\n },\n setWatchOtherSpecs: (otherSpecs: UnknownSpec): void => {\n setWatchOtherSpecs(otherSpecs);\n },\n }\n : undefined;\n }, [withRunQueryButton]);\n\n useImperativeHandle(ref, () => ({ flushChanges: runQueryHandler }));\n\n return (\n <Box {...others}>\n <Box sx={{ display: 'flex', flexDirection: 'row' }}>\n <PluginKindSelect\n fullWidth={false}\n sx={{ mb: 2, minWidth: 120 }}\n margin=\"dense\"\n label={pluginKindLabel}\n pluginTypes={pluginTypes}\n disabled={isLoading}\n value={pendingSelection ? pendingSelection : value.selection}\n InputProps={{ readOnly: isReadonly }}\n error={!!error}\n helperText={error?.message}\n onChange={onSelectionChange}\n />\n\n {withRunQueryButton && !isLoading && (\n <Button\n data-testid=\"run_query_button\"\n variant=\"contained\"\n sx={{ marginTop: 1.5, marginBottom: 1.5, paddingTop: 0.5, marginLeft: 'auto' }}\n startIcon={<Reload />}\n onClick={runQueryHandler}\n >\n Run Query\n </Button>\n )}\n </Box>\n\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <PluginSpecEditor\n pluginSelection={value.selection}\n value={value.spec}\n onChange={onSpecChange}\n isReadonly={isReadonly}\n queryHandlerSettings={queryHandlerSettings}\n />\n </ErrorBoundary>\n </Box>\n );\n});\n\nPluginEditor.displayName = 'PluginEditor';\n"],"names":["Box","Button","Reload","ErrorAlert","ErrorBoundary","forwardRef","useCallback","useImperativeHandle","useMemo","useState","PluginKindSelect","PluginSpecEditor","usePluginEditor","PluginEditor","props","ref","value","withRunQueryButton","pluginTypes","pluginKindLabel","onChange","_","isReadonly","postExecuteRunQuery","refresh","others","pendingSelection","isLoading","error","onSelectionChange","onSpecChange","watchedQuery","setWatchQuery","spec","watchedOtherSpecs","setWatchOtherSpecs","runQueryHandler","query","queryHandlerSettings","runWithOnBlur","watchQueryChanges","otherSpecs","undefined","flushChanges","sx","display","flexDirection","fullWidth","mb","minWidth","margin","label","disabled","selection","InputProps","readOnly","helperText","message","data-testid","variant","marginTop","marginBottom","paddingTop","marginLeft","startIcon","onClick","FallbackComponent","pluginSelection","displayName"],"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,SAASA,GAAG,EAAEC,MAAM,QAAQ,gBAAgB;AAC5C,OAAOC,YAAY,yBAAyB;AAC5C,SAASC,UAAU,EAAEC,aAAa,QAAQ,yBAAyB;AACnE,SAASC,UAAU,EAAgBC,WAAW,EAAEC,mBAAmB,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,QAAQ;AAEtG,SAASC,gBAAgB,QAAQ,sBAAsB;AACvD,SAASC,gBAAgB,QAAQ,sBAAsB;AACvD,SAA6CC,eAAe,QAAQ,sBAAsB;AAE1F;;;;;;;CAOC,GAED,OAAO,MAAMC,6BAAeR,WAA+C,CAACS,OAAOC;IACjF,MAAM,EACJC,KAAK,EACLC,qBAAqB,IAAI,EACzBC,WAAW,EACXC,eAAe,EACfC,UAAUC,CAAC,EACXC,UAAU,EACVC,qBAAqBC,OAAO,EAC5B,GAAGC,QACJ,GAAGX;IACJ,MAAM,EAAEY,gBAAgB,EAAEC,SAAS,EAAEC,KAAK,EAAEC,iBAAiB,EAAEC,YAAY,EAAE,GAAGlB,gBAAgBE;IAEhG;;;;;;IAME,GACF,MAAM,CAACiB,cAAcC,cAAc,GAAGvB,SAAiBO,MAAMiB,IAAI,CAAC,QAAQ;IAC1E,MAAM,CAACC,mBAAmBC,mBAAmB,GAAG1B,SAAsBO,MAAMiB,IAAI;IAEhF,MAAMG,kBAAkB9B,YAAY;QAClCwB,aAAa;YAAE,GAAGd,MAAMiB,IAAI;YAAE,GAAGC,iBAAiB;YAAEG,OAAON;QAAa;QACxEP;IACF,GAAG;QAACR,MAAMiB,IAAI;QAAEH;QAAcC;QAAcG;QAAmBV;KAAQ;IAEvE,MAAMc,uBAAuB9B,QAAQ;QACnC,OAAOS,qBACH;YACEsB,eAAe;YACfC,mBAAmB,CAACH;gBAClBL,cAAcK;YAChB;YACAF,oBAAoB,CAACM;gBACnBN,mBAAmBM;YACrB;QACF,IACAC;IACN,GAAG;QAACzB;KAAmB;IAEvBV,oBAAoBQ,KAAK,IAAO,CAAA;YAAE4B,cAAcP;QAAgB,CAAA;IAEhE,qBACE,MAACpC;QAAK,GAAGyB,MAAM;;0BACb,MAACzB;gBAAI4C,IAAI;oBAAEC,SAAS;oBAAQC,eAAe;gBAAM;;kCAC/C,KAACpC;wBACCqC,WAAW;wBACXH,IAAI;4BAAEI,IAAI;4BAAGC,UAAU;wBAAI;wBAC3BC,QAAO;wBACPC,OAAOhC;wBACPD,aAAaA;wBACbkC,UAAUzB;wBACVX,OAAOU,mBAAmBA,mBAAmBV,MAAMqC,SAAS;wBAC5DC,YAAY;4BAAEC,UAAUjC;wBAAW;wBACnCM,OAAO,CAAC,CAACA;wBACT4B,YAAY5B,OAAO6B;wBACnBrC,UAAUS;;oBAGXZ,sBAAsB,CAACU,2BACtB,KAAC1B;wBACCyD,eAAY;wBACZC,SAAQ;wBACRf,IAAI;4BAAEgB,WAAW;4BAAKC,cAAc;4BAAKC,YAAY;4BAAKC,YAAY;wBAAO;wBAC7EC,yBAAW,KAAC9D;wBACZ+D,SAAS7B;kCACV;;;;0BAML,KAAChC;gBAAc8D,mBAAmB/D;0BAChC,cAAA,KAACQ;oBACCwD,iBAAiBnD,MAAMqC,SAAS;oBAChCrC,OAAOA,MAAMiB,IAAI;oBACjBb,UAAUU;oBACVR,YAAYA;oBACZgB,sBAAsBA;;;;;AAKhC,GAAG;AAEHzB,aAAauD,WAAW,GAAG"}
|
|
@@ -17,6 +17,10 @@ export interface PluginEditorProps extends Omit<BoxProps, OmittedMuiProps> {
|
|
|
17
17
|
isReadonly?: boolean;
|
|
18
18
|
withRunQueryButton?: boolean;
|
|
19
19
|
onChange: (next: PluginEditorValue) => void;
|
|
20
|
+
postExecuteRunQuery?: () => void;
|
|
21
|
+
}
|
|
22
|
+
export interface PluginEditorRef {
|
|
23
|
+
flushChanges?: () => void;
|
|
20
24
|
}
|
|
21
25
|
/**
|
|
22
26
|
* Props needed by the usePluginEditor hook.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-editor-api.d.ts","sourceRoot":"","sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAY,MAAM,kBAAkB,CAAC;AAGzD,OAAO,EAAe,UAAU,EAAE,MAAM,aAAa,CAAC;AAKtD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,qBAAqB,CAAC;IACjC,IAAI,EAAE,WAAW,CAAC;CACnB;AAID,KAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC;IACxE,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin-editor-api.d.ts","sourceRoot":"","sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,WAAW,EAAY,MAAM,kBAAkB,CAAC;AAGzD,OAAO,EAAe,UAAU,EAAE,MAAM,aAAa,CAAC;AAKtD,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,UAAU,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,qBAAqB,CAAC;IACjC,IAAI,EAAE,WAAW,CAAC;CACnB;AAID,KAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,iBAAkB,SAAQ,IAAI,CAAC,QAAQ,EAAE,eAAe,CAAC;IACxE,WAAW,EAAE,UAAU,EAAE,CAAC;IAC1B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,iBAAiB,CAAC;IACzB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,QAAQ,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5C,mBAAmB,CAAC,EAAE,MAAM,IAAI,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;CAC3B;AAKD;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG,IAAI,CAAC,iBAAiB,EAAE,aAAa,GAAG,OAAO,GAAG,UAAU,CAAC,GAAG;IACjG,uBAAuB,CAAC,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;CACvD,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG;IAC5D,gBAAgB,CAAC,EAAE,qBAAqB,CAAC;IACzC,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,iBAAiB,EAAE,CAAC,CAAC,EAAE,qBAAqB,KAAK,IAAI,CAAC;IACtD,YAAY,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAC1C,wBAAwB,EAAE,MAAM,IAAI,CAAC;CACtC,CAyHA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"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 { BoxProps } from '@mui/material';\nimport { UnknownSpec, useEvent } from '@perses-dev/core';\nimport { useState, useRef, useEffect } from 'react';\nimport { produce } from 'immer';\nimport { PanelPlugin, PluginType } from '../../model';\nimport { PluginKindSelectProps } from '../PluginKindSelect/PluginKindSelect';\nimport { PluginSpecEditorProps } from '../PluginSpecEditor/PluginSpecEditor';\nimport { usePlugin, usePluginRegistry } from '../../runtime';\n\nexport interface PluginEditorSelection {\n type: PluginType;\n kind: string;\n}\n\nexport interface PluginEditorValue {\n selection: PluginEditorSelection;\n spec: UnknownSpec;\n}\n\n// Props on MUI Box that we don't want people to pass because we're either redefining them or providing them in\n// this component\ntype OmittedMuiProps = 'children' | 'value' | 'onChange';\n\nexport interface PluginEditorProps extends Omit<BoxProps, OmittedMuiProps> {\n pluginTypes: PluginType[];\n pluginKindLabel: string;\n value: PluginEditorValue;\n isReadonly?: boolean;\n withRunQueryButton?: boolean;\n onChange: (next: PluginEditorValue) => void;\n}\n\ntype PreviousSpecState = Record<string, Record<string, UnknownSpec>>;\ntype HideQueryEditorState = Record<string, boolean>;\n\n/**\n * Props needed by the usePluginEditor hook.\n */\nexport type UsePluginEditorProps = Pick<PluginEditorProps, 'pluginTypes' | 'value' | 'onChange'> & {\n onHideQueryEditorChange?: (isHidden: boolean) => void;\n};\n\n/**\n * Returns the state/handlers that power the `PluginEditor` component. Useful for custom components that want to provide\n * a different UI, but want the same behavior of changing `kind` and `spec` together on plugin kind changes. Also\n * remembers previous `spec` values that it's seen, allowing and restores those values if a user switches the plugin\n * kind back.\n */\nexport function usePluginEditor(props: UsePluginEditorProps): {\n pendingSelection?: PluginEditorSelection;\n isLoading: boolean;\n error: Error | null;\n onSelectionChange: (s: PluginEditorSelection) => void;\n onSpecChange: (next: UnknownSpec) => void;\n rememberCurrentSpecState: () => void;\n} {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const { pluginTypes, value, onHideQueryEditorChange = (): void => {} } = props; // setting onHideQueryEditorChange to empty function here because useEvent requires a function\n\n // Keep a stable reference, so we don't run the effect below when we don't need to\n const onChange = useEvent(props.onChange);\n const onHideQuery = useEvent(onHideQueryEditorChange);\n\n // The previous spec state for PluginType and kind and a helper function for remembering current values\n const prevSpecState = useRef<PreviousSpecState>({\n [value.selection.type]: { [value.selection.kind]: value.spec },\n });\n const rememberCurrentSpecState = useEvent(() => {\n let byPluginType = prevSpecState.current[value.selection.type];\n if (byPluginType === undefined) {\n byPluginType = {};\n prevSpecState.current[value.selection.type] = byPluginType;\n }\n byPluginType[value.selection.kind] = value.spec;\n });\n\n // The previous hide query state for each panel kind\n const hideQueryState = useRef<HideQueryEditorState>({\n [value.selection.kind]: false,\n });\n\n const { defaultPluginKinds } = usePluginRegistry();\n const defaultPluginType = pluginTypes[0];\n const defaultPluginKind = defaultPluginType ? defaultPluginKinds?.[defaultPluginType] : undefined;\n const defaultPluginSelection =\n defaultPluginType && defaultPluginKind\n ? {\n type: defaultPluginType,\n kind: defaultPluginKind,\n }\n : undefined;\n const initPendingSelection = !value.selection && defaultPluginSelection ? defaultPluginSelection : undefined;\n\n // When kind changes and we haven't loaded that plugin before, we will need to enter a \"pending\" state so that we\n // can generate proper initial spec values that match the new plugin kind\n const [pendingSelection, setPendingSelection] = useState<PluginEditorSelection | undefined>(initPendingSelection);\n\n // Take a default kind in case user write explicitly an empty kind in the initial value\n useEffect(() => {\n if (value.selection.kind === '') {\n value.selection.kind = defaultPluginKind || '';\n }\n }, [value.selection, defaultPluginKind]);\n\n const { data: plugin, isFetching, error } = usePlugin(pendingSelection?.type, pendingSelection?.kind || '');\n\n useEffect(() => {\n // Nothing to do if no new plugin kind is pending\n if (!pendingSelection) return;\n\n // Can't get spec value until we have a plugin\n if (plugin === undefined) return;\n\n // Fire an onChange to change to the pending kind with initial values from the plugin\n rememberCurrentSpecState();\n onChange({\n selection: pendingSelection,\n spec: plugin.createInitialOptions ? plugin.createInitialOptions() : {},\n });\n\n if (pendingSelection.type === 'Panel') {\n const panelPlugin = plugin as PanelPlugin;\n hideQueryState.current[pendingSelection.kind] = !!panelPlugin.hideQueryEditor;\n if (!!panelPlugin.hideQueryEditor !== hideQueryState.current[value.selection.kind]) {\n onHideQuery(!!panelPlugin.hideQueryEditor);\n }\n }\n setPendingSelection(undefined);\n }, [pendingSelection, plugin, rememberCurrentSpecState, onChange, onHideQuery, hideQueryState, value.selection]);\n\n /**\n * When the user tries to change the plugin kind, make sure we have the correct spec for that plugin kind before we\n * make the switch.\n */\n const onSelectionChange: PluginKindSelectProps['onChange'] = (nextSelection) => {\n // If we already have state for this plugin type/kind from a previous selection, just use it\n const previousState = prevSpecState.current[nextSelection.type]?.[nextSelection.kind];\n if (previousState !== undefined) {\n rememberCurrentSpecState();\n onChange({\n selection: nextSelection,\n spec: previousState,\n });\n } else {\n // Otherwise, kick off the async loading process\n setPendingSelection(nextSelection);\n }\n\n if (\n nextSelection.type === 'Panel' &&\n hideQueryState.current[nextSelection.kind] !== undefined &&\n hideQueryState.current[value.selection.kind] !== hideQueryState.current[nextSelection.kind]\n ) {\n onHideQuery(!!hideQueryState.current[nextSelection.kind]);\n }\n };\n\n /**\n * Spec changes are independent and always just set the spec state.\n */\n const onSpecChange: PluginSpecEditorProps['onChange'] = (next) => {\n onChange(\n produce(value, (draft) => {\n draft.spec = next;\n })\n );\n };\n\n return {\n pendingSelection,\n isLoading: isFetching,\n error,\n onSelectionChange,\n onSpecChange,\n rememberCurrentSpecState,\n };\n}\n"],"names":["useEvent","useState","useRef","useEffect","produce","usePlugin","usePluginRegistry","usePluginEditor","props","pluginTypes","value","onHideQueryEditorChange","onChange","onHideQuery","prevSpecState","selection","type","kind","spec","rememberCurrentSpecState","byPluginType","current","undefined","hideQueryState","defaultPluginKinds","defaultPluginType","defaultPluginKind","defaultPluginSelection","initPendingSelection","pendingSelection","setPendingSelection","data","plugin","isFetching","error","createInitialOptions","panelPlugin","hideQueryEditor","onSelectionChange","nextSelection","previousState","onSpecChange","next","draft","isLoading"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/PluginEditor/plugin-editor-api.ts"],"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 { BoxProps } from '@mui/material';\nimport { UnknownSpec, useEvent } from '@perses-dev/core';\nimport { useState, useRef, useEffect } from 'react';\nimport { produce } from 'immer';\nimport { PanelPlugin, PluginType } from '../../model';\nimport { PluginKindSelectProps } from '../PluginKindSelect/PluginKindSelect';\nimport { PluginSpecEditorProps } from '../PluginSpecEditor/PluginSpecEditor';\nimport { usePlugin, usePluginRegistry } from '../../runtime';\n\nexport interface PluginEditorSelection {\n type: PluginType;\n kind: string;\n}\n\nexport interface PluginEditorValue {\n selection: PluginEditorSelection;\n spec: UnknownSpec;\n}\n\n// Props on MUI Box that we don't want people to pass because we're either redefining them or providing them in\n// this component\ntype OmittedMuiProps = 'children' | 'value' | 'onChange';\n\nexport interface PluginEditorProps extends Omit<BoxProps, OmittedMuiProps> {\n pluginTypes: PluginType[];\n pluginKindLabel: string;\n value: PluginEditorValue;\n isReadonly?: boolean;\n withRunQueryButton?: boolean;\n onChange: (next: PluginEditorValue) => void;\n postExecuteRunQuery?: () => void;\n}\n\nexport interface PluginEditorRef {\n flushChanges?: () => void;\n}\n\ntype PreviousSpecState = Record<string, Record<string, UnknownSpec>>;\ntype HideQueryEditorState = Record<string, boolean>;\n\n/**\n * Props needed by the usePluginEditor hook.\n */\nexport type UsePluginEditorProps = Pick<PluginEditorProps, 'pluginTypes' | 'value' | 'onChange'> & {\n onHideQueryEditorChange?: (isHidden: boolean) => void;\n};\n\n/**\n * Returns the state/handlers that power the `PluginEditor` component. Useful for custom components that want to provide\n * a different UI, but want the same behavior of changing `kind` and `spec` together on plugin kind changes. Also\n * remembers previous `spec` values that it's seen, allowing and restores those values if a user switches the plugin\n * kind back.\n */\nexport function usePluginEditor(props: UsePluginEditorProps): {\n pendingSelection?: PluginEditorSelection;\n isLoading: boolean;\n error: Error | null;\n onSelectionChange: (s: PluginEditorSelection) => void;\n onSpecChange: (next: UnknownSpec) => void;\n rememberCurrentSpecState: () => void;\n} {\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const { pluginTypes, value, onHideQueryEditorChange = (): void => {} } = props; // setting onHideQueryEditorChange to empty function here because useEvent requires a function\n\n // Keep a stable reference, so we don't run the effect below when we don't need to\n const onChange = useEvent(props.onChange);\n const onHideQuery = useEvent(onHideQueryEditorChange);\n\n // The previous spec state for PluginType and kind and a helper function for remembering current values\n const prevSpecState = useRef<PreviousSpecState>({\n [value.selection.type]: { [value.selection.kind]: value.spec },\n });\n const rememberCurrentSpecState = useEvent(() => {\n let byPluginType = prevSpecState.current[value.selection.type];\n if (byPluginType === undefined) {\n byPluginType = {};\n prevSpecState.current[value.selection.type] = byPluginType;\n }\n byPluginType[value.selection.kind] = value.spec;\n });\n\n // The previous hide query state for each panel kind\n const hideQueryState = useRef<HideQueryEditorState>({\n [value.selection.kind]: false,\n });\n\n const { defaultPluginKinds } = usePluginRegistry();\n const defaultPluginType = pluginTypes[0];\n const defaultPluginKind = defaultPluginType ? defaultPluginKinds?.[defaultPluginType] : undefined;\n const defaultPluginSelection =\n defaultPluginType && defaultPluginKind\n ? {\n type: defaultPluginType,\n kind: defaultPluginKind,\n }\n : undefined;\n const initPendingSelection = !value.selection && defaultPluginSelection ? defaultPluginSelection : undefined;\n\n // When kind changes and we haven't loaded that plugin before, we will need to enter a \"pending\" state so that we\n // can generate proper initial spec values that match the new plugin kind\n const [pendingSelection, setPendingSelection] = useState<PluginEditorSelection | undefined>(initPendingSelection);\n\n // Take a default kind in case user write explicitly an empty kind in the initial value\n useEffect(() => {\n if (value.selection.kind === '') {\n value.selection.kind = defaultPluginKind || '';\n }\n }, [value.selection, defaultPluginKind]);\n\n const { data: plugin, isFetching, error } = usePlugin(pendingSelection?.type, pendingSelection?.kind || '');\n\n useEffect(() => {\n // Nothing to do if no new plugin kind is pending\n if (!pendingSelection) return;\n\n // Can't get spec value until we have a plugin\n if (plugin === undefined) return;\n\n // Fire an onChange to change to the pending kind with initial values from the plugin\n rememberCurrentSpecState();\n onChange({\n selection: pendingSelection,\n spec: plugin.createInitialOptions ? plugin.createInitialOptions() : {},\n });\n\n if (pendingSelection.type === 'Panel') {\n const panelPlugin = plugin as PanelPlugin;\n hideQueryState.current[pendingSelection.kind] = !!panelPlugin.hideQueryEditor;\n if (!!panelPlugin.hideQueryEditor !== hideQueryState.current[value.selection.kind]) {\n onHideQuery(!!panelPlugin.hideQueryEditor);\n }\n }\n setPendingSelection(undefined);\n }, [pendingSelection, plugin, rememberCurrentSpecState, onChange, onHideQuery, hideQueryState, value.selection]);\n\n /**\n * When the user tries to change the plugin kind, make sure we have the correct spec for that plugin kind before we\n * make the switch.\n */\n const onSelectionChange: PluginKindSelectProps['onChange'] = (nextSelection) => {\n // If we already have state for this plugin type/kind from a previous selection, just use it\n const previousState = prevSpecState.current[nextSelection.type]?.[nextSelection.kind];\n if (previousState !== undefined) {\n rememberCurrentSpecState();\n onChange({\n selection: nextSelection,\n spec: previousState,\n });\n } else {\n // Otherwise, kick off the async loading process\n setPendingSelection(nextSelection);\n }\n\n if (\n nextSelection.type === 'Panel' &&\n hideQueryState.current[nextSelection.kind] !== undefined &&\n hideQueryState.current[value.selection.kind] !== hideQueryState.current[nextSelection.kind]\n ) {\n onHideQuery(!!hideQueryState.current[nextSelection.kind]);\n }\n };\n\n /**\n * Spec changes are independent and always just set the spec state.\n */\n const onSpecChange: PluginSpecEditorProps['onChange'] = (next) => {\n onChange(\n produce(value, (draft) => {\n draft.spec = next;\n })\n );\n };\n\n return {\n pendingSelection,\n isLoading: isFetching,\n error,\n onSelectionChange,\n onSpecChange,\n rememberCurrentSpecState,\n };\n}\n"],"names":["useEvent","useState","useRef","useEffect","produce","usePlugin","usePluginRegistry","usePluginEditor","props","pluginTypes","value","onHideQueryEditorChange","onChange","onHideQuery","prevSpecState","selection","type","kind","spec","rememberCurrentSpecState","byPluginType","current","undefined","hideQueryState","defaultPluginKinds","defaultPluginType","defaultPluginKind","defaultPluginSelection","initPendingSelection","pendingSelection","setPendingSelection","data","plugin","isFetching","error","createInitialOptions","panelPlugin","hideQueryEditor","onSelectionChange","nextSelection","previousState","onSpecChange","next","draft","isLoading"],"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;AAGjC,SAAsBA,QAAQ,QAAQ,mBAAmB;AACzD,SAASC,QAAQ,EAAEC,MAAM,EAAEC,SAAS,QAAQ,QAAQ;AACpD,SAASC,OAAO,QAAQ,QAAQ;AAIhC,SAASC,SAAS,EAAEC,iBAAiB,QAAQ,gBAAgB;AAwC7D;;;;;CAKC,GACD,OAAO,SAASC,gBAAgBC,KAA2B;IAQzD,gEAAgE;IAChE,MAAM,EAAEC,WAAW,EAAEC,KAAK,EAAEC,0BAA0B,KAAa,CAAC,EAAE,GAAGH,OAAO,8FAA8F;IAE9K,kFAAkF;IAClF,MAAMI,WAAWZ,SAASQ,MAAMI,QAAQ;IACxC,MAAMC,cAAcb,SAASW;IAE7B,uGAAuG;IACvG,MAAMG,gBAAgBZ,OAA0B;QAC9C,CAACQ,MAAMK,SAAS,CAACC,IAAI,CAAC,EAAE;YAAE,CAACN,MAAMK,SAAS,CAACE,IAAI,CAAC,EAAEP,MAAMQ,IAAI;QAAC;IAC/D;IACA,MAAMC,2BAA2BnB,SAAS;QACxC,IAAIoB,eAAeN,cAAcO,OAAO,CAACX,MAAMK,SAAS,CAACC,IAAI,CAAC;QAC9D,IAAII,iBAAiBE,WAAW;YAC9BF,eAAe,CAAC;YAChBN,cAAcO,OAAO,CAACX,MAAMK,SAAS,CAACC,IAAI,CAAC,GAAGI;QAChD;QACAA,YAAY,CAACV,MAAMK,SAAS,CAACE,IAAI,CAAC,GAAGP,MAAMQ,IAAI;IACjD;IAEA,oDAAoD;IACpD,MAAMK,iBAAiBrB,OAA6B;QAClD,CAACQ,MAAMK,SAAS,CAACE,IAAI,CAAC,EAAE;IAC1B;IAEA,MAAM,EAAEO,kBAAkB,EAAE,GAAGlB;IAC/B,MAAMmB,oBAAoBhB,WAAW,CAAC,EAAE;IACxC,MAAMiB,oBAAoBD,oBAAoBD,oBAAoB,CAACC,kBAAkB,GAAGH;IACxF,MAAMK,yBACJF,qBAAqBC,oBACjB;QACEV,MAAMS;QACNR,MAAMS;IACR,IACAJ;IACN,MAAMM,uBAAuB,CAAClB,MAAMK,SAAS,IAAIY,yBAAyBA,yBAAyBL;IAEnG,iHAAiH;IACjH,yEAAyE;IACzE,MAAM,CAACO,kBAAkBC,oBAAoB,GAAG7B,SAA4C2B;IAE5F,uFAAuF;IACvFzB,UAAU;QACR,IAAIO,MAAMK,SAAS,CAACE,IAAI,KAAK,IAAI;YAC/BP,MAAMK,SAAS,CAACE,IAAI,GAAGS,qBAAqB;QAC9C;IACF,GAAG;QAAChB,MAAMK,SAAS;QAAEW;KAAkB;IAEvC,MAAM,EAAEK,MAAMC,MAAM,EAAEC,UAAU,EAAEC,KAAK,EAAE,GAAG7B,UAAUwB,kBAAkBb,MAAMa,kBAAkBZ,QAAQ;IAExGd,UAAU;QACR,iDAAiD;QACjD,IAAI,CAAC0B,kBAAkB;QAEvB,8CAA8C;QAC9C,IAAIG,WAAWV,WAAW;QAE1B,qFAAqF;QACrFH;QACAP,SAAS;YACPG,WAAWc;YACXX,MAAMc,OAAOG,oBAAoB,GAAGH,OAAOG,oBAAoB,KAAK,CAAC;QACvE;QAEA,IAAIN,iBAAiBb,IAAI,KAAK,SAAS;YACrC,MAAMoB,cAAcJ;YACpBT,eAAeF,OAAO,CAACQ,iBAAiBZ,IAAI,CAAC,GAAG,CAAC,CAACmB,YAAYC,eAAe;YAC7E,IAAI,CAAC,CAACD,YAAYC,eAAe,KAAKd,eAAeF,OAAO,CAACX,MAAMK,SAAS,CAACE,IAAI,CAAC,EAAE;gBAClFJ,YAAY,CAAC,CAACuB,YAAYC,eAAe;YAC3C;QACF;QACAP,oBAAoBR;IACtB,GAAG;QAACO;QAAkBG;QAAQb;QAA0BP;QAAUC;QAAaU;QAAgBb,MAAMK,SAAS;KAAC;IAE/G;;;GAGC,GACD,MAAMuB,oBAAuD,CAACC;QAC5D,4FAA4F;QAC5F,MAAMC,gBAAgB1B,cAAcO,OAAO,CAACkB,cAAcvB,IAAI,CAAC,EAAE,CAACuB,cAActB,IAAI,CAAC;QACrF,IAAIuB,kBAAkBlB,WAAW;YAC/BH;YACAP,SAAS;gBACPG,WAAWwB;gBACXrB,MAAMsB;YACR;QACF,OAAO;YACL,gDAAgD;YAChDV,oBAAoBS;QACtB;QAEA,IACEA,cAAcvB,IAAI,KAAK,WACvBO,eAAeF,OAAO,CAACkB,cAActB,IAAI,CAAC,KAAKK,aAC/CC,eAAeF,OAAO,CAACX,MAAMK,SAAS,CAACE,IAAI,CAAC,KAAKM,eAAeF,OAAO,CAACkB,cAActB,IAAI,CAAC,EAC3F;YACAJ,YAAY,CAAC,CAACU,eAAeF,OAAO,CAACkB,cAActB,IAAI,CAAC;QAC1D;IACF;IAEA;;GAEC,GACD,MAAMwB,eAAkD,CAACC;QACvD9B,SACER,QAAQM,OAAO,CAACiC;YACdA,MAAMzB,IAAI,GAAGwB;QACf;IAEJ;IAEA,OAAO;QACLb;QACAe,WAAWX;QACXC;QACAI;QACAG;QACAtB;IACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"sourcesContent":["// Copyright 2024 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 RefreshIcon from 'mdi-material-ui/Refresh';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomIn from 'mdi-material-ui/PlusCircleOutline';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomOut from 'mdi-material-ui/MinusCircleOutline';\nimport { Stack } from '@mui/material';\nimport {\n RefreshIntervalPicker,\n InfoTooltip,\n TimeOption,\n ToolbarIconButton,\n TimeRangeSelector,\n buildRelativeTimeOption,\n} from '@perses-dev/components';\nimport { AbsoluteTimeRange, DurationString, parseDurationString, RelativeTimeRange } from '@perses-dev/core';\nimport { ReactElement, useCallback } from 'react';\nimport { TOOLTIP_TEXT } from '../../constants';\nimport {\n useTimeRange,\n useShowCustomTimeRangeSetting,\n useTimeRangeOptionsSetting,\n useShowZoomRangeSetting,\n} from '../../runtime';\n\nexport const DEFAULT_REFRESH_INTERVAL_OPTIONS: TimeOption[] = [\n { value: { pastDuration: '0s' }, display: 'Off' },\n { value: { pastDuration: '5s' }, display: '5s' },\n { value: { pastDuration: '10s' }, display: '10s' },\n { value: { pastDuration: '15s' }, display: '15s' },\n { value: { pastDuration: '30s' }, display: '30s' },\n { value: { pastDuration: '60s' }, display: '1m' },\n];\n\nconst DEFAULT_HEIGHT = '34px';\n\ninterface TimeRangeControlsProps {\n // The controls look best at heights >= 28 pixels\n heightPx?: number;\n showTimeRangeSelector?: boolean;\n showRefreshButton?: boolean;\n showRefreshInterval?: boolean;\n showCustomTimeRange?: boolean;\n showZoomButtons?: boolean;\n timePresets?: TimeOption[];\n}\n\nexport function TimeRangeControls({\n heightPx,\n showTimeRangeSelector = true,\n showRefreshButton = true,\n showRefreshInterval = true,\n showCustomTimeRange,\n showZoomButtons = true,\n timePresets,\n}: TimeRangeControlsProps): ReactElement {\n const { timeRange, setTimeRange, refresh, refreshInterval, setRefreshInterval } = useTimeRange();\n\n const showCustomTimeRangeValue = useShowCustomTimeRangeSetting(showCustomTimeRange);\n const showZoomInOutButtons = useShowZoomRangeSetting(showZoomButtons);\n const timePresetsValue = useTimeRangeOptionsSetting(timePresets);\n\n // Convert height to a string, then use the string for styling\n const height = heightPx === undefined ? DEFAULT_HEIGHT : `${heightPx}px`;\n\n // add time preset if one does not match duration given in time range\n if (\n 'pastDuration' in timeRange &&\n !timePresetsValue.some((option) => option.value.pastDuration === timeRange['pastDuration'])\n ) {\n timePresetsValue.push(buildRelativeTimeOption(timeRange['pastDuration']));\n }\n\n // set the new refresh interval both in the dashboard context & as query param\n const handleRefreshIntervalChange = useCallback(\n (duration: DurationString) => {\n setRefreshInterval(duration);\n },\n [setRefreshInterval]\n );\n\n const fromDurationToMillis = (strDuration: string): number => {\n const duration = parseDurationString(strDuration);\n const millis =\n // eslint-disable-next-line prettier/prettier\n ((duration.seconds ?? 0) +\n (duration.minutes ?? 0) * 60 +\n (duration.hours ?? 0) * 3600 +\n (duration.days ?? 0) * 86400 +\n (duration.weeks ?? 0) * 7 * 86400 +\n (duration.months ?? 0) * 30.436875 * 86400 + // avg month duration is ok for zoom purposes\n (duration.years ?? 0) * 365.2425 * 86400) * // avg year duration is ok for zoom purposes\n // eslint-disable-next-line prettier/prettier\n 1000; // to milliseconds\n return millis;\n };\n\n // Function to double current time range, adding 50% before current start and 50% after current end\n const doubleTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd, extendEndsBy;\n const now = new Date();\n if (Object.hasOwn(timeRange, 'start')) {\n // current range is absolute\n const absVal = timeRange as AbsoluteTimeRange;\n extendEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 2; // half it to add 50% before current start and after current end\n newStart = new Date(absVal.start.getTime() - extendEndsBy);\n newEnd = new Date(absVal.end.getTime() + extendEndsBy);\n } else {\n // current range is relative\n const relVal = timeRange as RelativeTimeRange;\n extendEndsBy = fromDurationToMillis(relVal.pastDuration) / 2;\n newEnd = typeof relVal.end === 'undefined' ? now : new Date(relVal.end.getTime() + extendEndsBy);\n newStart = new Date(newEnd.getTime() - extendEndsBy * 4);\n }\n if (newEnd.getTime() > now.getTime()) {\n // if the new computed end is in the future\n newEnd = now;\n newStart.setTime(now.getTime() - extendEndsBy * 4);\n }\n if (newStart.getTime() < 1) {\n newStart.setTime(1);\n }\n return { start: newStart, end: newEnd };\n };\n\n // Function to half current time range, cutting 25% before current start and 25% after current end\n const halfTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd;\n if (Object.hasOwn(timeRange, 'start')) {\n const absVal = timeRange as AbsoluteTimeRange;\n const shrinkEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 4;\n newStart = new Date(absVal.start.getTime() + shrinkEndsBy);\n newEnd = new Date(absVal.end.getTime() - shrinkEndsBy);\n } else {\n const relVal = timeRange as RelativeTimeRange;\n const shrinkEndsBy = fromDurationToMillis(relVal.pastDuration) / 4; // 25% of it to cut after current start and before current end\n const endIsAbsolute = typeof relVal.end !== 'undefined';\n newEnd = endIsAbsolute ? new Date(relVal.end!.getTime() - shrinkEndsBy) : new Date();\n newStart = new Date(newEnd.getTime() - shrinkEndsBy * 2);\n }\n if (newStart.getTime() >= newEnd.getTime() - 1000) {\n newStart.setTime(newEnd.getTime() - 1000);\n }\n return { start: newStart, end: newEnd };\n };\n\n const setHalfTimeRange = (): void => setTimeRange(halfTimeRange());\n const setDoubleTimeRange = (): void => setTimeRange(doubleTimeRange());\n\n return (\n <Stack direction=\"row\" spacing={1}>\n {showTimeRangeSelector && (\n <TimeRangeSelector\n timeOptions={timePresetsValue}\n value={timeRange}\n onChange={setTimeRange}\n height={height}\n showCustomTimeRange={showCustomTimeRangeValue}\n />\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomOut}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomOut} onClick={setDoubleTimeRange} sx={{ height }}>\n <ZoomOut />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomIn}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomIn} onClick={setHalfTimeRange} sx={{ height }}>\n <ZoomIn />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshButton && (\n <InfoTooltip description={TOOLTIP_TEXT.refresh}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.refresh} onClick={refresh} sx={{ height }}>\n <RefreshIcon />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshInterval && (\n <InfoTooltip description={TOOLTIP_TEXT.refreshInterval}>\n <RefreshIntervalPicker\n timeOptions={DEFAULT_REFRESH_INTERVAL_OPTIONS}\n value={refreshInterval}\n onChange={handleRefreshIntervalChange}\n height={height}\n />\n </InfoTooltip>\n )}\n </Stack>\n );\n}\n"],"names":["RefreshIcon","ZoomIn","ZoomOut","Stack","RefreshIntervalPicker","InfoTooltip","ToolbarIconButton","TimeRangeSelector","buildRelativeTimeOption","parseDurationString","useCallback","TOOLTIP_TEXT","useTimeRange","useShowCustomTimeRangeSetting","useTimeRangeOptionsSetting","useShowZoomRangeSetting","DEFAULT_REFRESH_INTERVAL_OPTIONS","value","pastDuration","display","DEFAULT_HEIGHT","TimeRangeControls","heightPx","showTimeRangeSelector","showRefreshButton","showRefreshInterval","showCustomTimeRange","showZoomButtons","timePresets","timeRange","setTimeRange","refresh","refreshInterval","setRefreshInterval","showCustomTimeRangeValue","showZoomInOutButtons","timePresetsValue","height","undefined","some","option","push","handleRefreshIntervalChange","duration","fromDurationToMillis","strDuration","millis","seconds","minutes","hours","days","weeks","months","years","doubleTimeRange","newStart","newEnd","extendEndsBy","now","Date","Object","hasOwn","absVal","end","getTime","start","relVal","setTime","halfTimeRange","shrinkEndsBy","endIsAbsolute","setHalfTimeRange","setDoubleTimeRange","direction","spacing","timeOptions","onChange","description","zoomOut","aria-label","onClick","sx","zoomIn"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/TimeRangeControls/TimeRangeControls.tsx"],"sourcesContent":["// Copyright 2024 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 RefreshIcon from 'mdi-material-ui/Refresh';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomIn from 'mdi-material-ui/PlusCircleOutline';\n// eslint-disable-next-line import/no-duplicates\nimport ZoomOut from 'mdi-material-ui/MinusCircleOutline';\nimport { Stack } from '@mui/material';\nimport {\n RefreshIntervalPicker,\n InfoTooltip,\n TimeOption,\n ToolbarIconButton,\n TimeRangeSelector,\n buildRelativeTimeOption,\n} from '@perses-dev/components';\nimport { AbsoluteTimeRange, DurationString, parseDurationString, RelativeTimeRange } from '@perses-dev/core';\nimport { ReactElement, useCallback } from 'react';\nimport { TOOLTIP_TEXT } from '../../constants';\nimport {\n useTimeRange,\n useShowCustomTimeRangeSetting,\n useTimeRangeOptionsSetting,\n useShowZoomRangeSetting,\n} from '../../runtime';\n\nexport const DEFAULT_REFRESH_INTERVAL_OPTIONS: TimeOption[] = [\n { value: { pastDuration: '0s' }, display: 'Off' },\n { value: { pastDuration: '5s' }, display: '5s' },\n { value: { pastDuration: '10s' }, display: '10s' },\n { value: { pastDuration: '15s' }, display: '15s' },\n { value: { pastDuration: '30s' }, display: '30s' },\n { value: { pastDuration: '60s' }, display: '1m' },\n];\n\nconst DEFAULT_HEIGHT = '34px';\n\ninterface TimeRangeControlsProps {\n // The controls look best at heights >= 28 pixels\n heightPx?: number;\n showTimeRangeSelector?: boolean;\n showRefreshButton?: boolean;\n showRefreshInterval?: boolean;\n showCustomTimeRange?: boolean;\n showZoomButtons?: boolean;\n timePresets?: TimeOption[];\n}\n\nexport function TimeRangeControls({\n heightPx,\n showTimeRangeSelector = true,\n showRefreshButton = true,\n showRefreshInterval = true,\n showCustomTimeRange,\n showZoomButtons = true,\n timePresets,\n}: TimeRangeControlsProps): ReactElement {\n const { timeRange, setTimeRange, refresh, refreshInterval, setRefreshInterval } = useTimeRange();\n\n const showCustomTimeRangeValue = useShowCustomTimeRangeSetting(showCustomTimeRange);\n const showZoomInOutButtons = useShowZoomRangeSetting(showZoomButtons);\n const timePresetsValue = useTimeRangeOptionsSetting(timePresets);\n\n // Convert height to a string, then use the string for styling\n const height = heightPx === undefined ? DEFAULT_HEIGHT : `${heightPx}px`;\n\n // add time preset if one does not match duration given in time range\n if (\n 'pastDuration' in timeRange &&\n !timePresetsValue.some((option) => option.value.pastDuration === timeRange['pastDuration'])\n ) {\n timePresetsValue.push(buildRelativeTimeOption(timeRange['pastDuration']));\n }\n\n // set the new refresh interval both in the dashboard context & as query param\n const handleRefreshIntervalChange = useCallback(\n (duration: DurationString) => {\n setRefreshInterval(duration);\n },\n [setRefreshInterval]\n );\n\n const fromDurationToMillis = (strDuration: string): number => {\n const duration = parseDurationString(strDuration);\n const millis =\n // eslint-disable-next-line prettier/prettier\n ((duration.seconds ?? 0) +\n (duration.minutes ?? 0) * 60 +\n (duration.hours ?? 0) * 3600 +\n (duration.days ?? 0) * 86400 +\n (duration.weeks ?? 0) * 7 * 86400 +\n (duration.months ?? 0) * 30.436875 * 86400 + // avg month duration is ok for zoom purposes\n (duration.years ?? 0) * 365.2425 * 86400) * // avg year duration is ok for zoom purposes\n // eslint-disable-next-line prettier/prettier\n 1000; // to milliseconds\n return millis;\n };\n\n // Function to double current time range, adding 50% before current start and 50% after current end\n const doubleTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd, extendEndsBy;\n const now = new Date();\n if (Object.hasOwn(timeRange, 'start')) {\n // current range is absolute\n const absVal = timeRange as AbsoluteTimeRange;\n extendEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 2; // half it to add 50% before current start and after current end\n newStart = new Date(absVal.start.getTime() - extendEndsBy);\n newEnd = new Date(absVal.end.getTime() + extendEndsBy);\n } else {\n // current range is relative\n const relVal = timeRange as RelativeTimeRange;\n extendEndsBy = fromDurationToMillis(relVal.pastDuration) / 2;\n newEnd = typeof relVal.end === 'undefined' ? now : new Date(relVal.end.getTime() + extendEndsBy);\n newStart = new Date(newEnd.getTime() - extendEndsBy * 4);\n }\n if (newEnd.getTime() > now.getTime()) {\n // if the new computed end is in the future\n newEnd = now;\n newStart.setTime(now.getTime() - extendEndsBy * 4);\n }\n if (newStart.getTime() < 1) {\n newStart.setTime(1);\n }\n return { start: newStart, end: newEnd };\n };\n\n // Function to half current time range, cutting 25% before current start and 25% after current end\n const halfTimeRange = (): AbsoluteTimeRange => {\n let newStart, newEnd;\n if (Object.hasOwn(timeRange, 'start')) {\n const absVal = timeRange as AbsoluteTimeRange;\n const shrinkEndsBy = (absVal.end.getTime() - absVal.start.getTime()) / 4;\n newStart = new Date(absVal.start.getTime() + shrinkEndsBy);\n newEnd = new Date(absVal.end.getTime() - shrinkEndsBy);\n } else {\n const relVal = timeRange as RelativeTimeRange;\n const shrinkEndsBy = fromDurationToMillis(relVal.pastDuration) / 4; // 25% of it to cut after current start and before current end\n const endIsAbsolute = typeof relVal.end !== 'undefined';\n newEnd = endIsAbsolute ? new Date(relVal.end!.getTime() - shrinkEndsBy) : new Date();\n newStart = new Date(newEnd.getTime() - shrinkEndsBy * 2);\n }\n if (newStart.getTime() >= newEnd.getTime() - 1000) {\n newStart.setTime(newEnd.getTime() - 1000);\n }\n return { start: newStart, end: newEnd };\n };\n\n const setHalfTimeRange = (): void => setTimeRange(halfTimeRange());\n const setDoubleTimeRange = (): void => setTimeRange(doubleTimeRange());\n\n return (\n <Stack direction=\"row\" spacing={1}>\n {showTimeRangeSelector && (\n <TimeRangeSelector\n timeOptions={timePresetsValue}\n value={timeRange}\n onChange={setTimeRange}\n height={height}\n showCustomTimeRange={showCustomTimeRangeValue}\n />\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomOut}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomOut} onClick={setDoubleTimeRange} sx={{ height }}>\n <ZoomOut />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showZoomInOutButtons && (\n <InfoTooltip description={TOOLTIP_TEXT.zoomIn}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.zoomIn} onClick={setHalfTimeRange} sx={{ height }}>\n <ZoomIn />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshButton && (\n <InfoTooltip description={TOOLTIP_TEXT.refresh}>\n <ToolbarIconButton aria-label={TOOLTIP_TEXT.refresh} onClick={refresh} sx={{ height }}>\n <RefreshIcon />\n </ToolbarIconButton>\n </InfoTooltip>\n )}\n {showRefreshInterval && (\n <InfoTooltip description={TOOLTIP_TEXT.refreshInterval}>\n <RefreshIntervalPicker\n timeOptions={DEFAULT_REFRESH_INTERVAL_OPTIONS}\n value={refreshInterval}\n onChange={handleRefreshIntervalChange}\n height={height}\n />\n </InfoTooltip>\n )}\n </Stack>\n );\n}\n"],"names":["RefreshIcon","ZoomIn","ZoomOut","Stack","RefreshIntervalPicker","InfoTooltip","ToolbarIconButton","TimeRangeSelector","buildRelativeTimeOption","parseDurationString","useCallback","TOOLTIP_TEXT","useTimeRange","useShowCustomTimeRangeSetting","useTimeRangeOptionsSetting","useShowZoomRangeSetting","DEFAULT_REFRESH_INTERVAL_OPTIONS","value","pastDuration","display","DEFAULT_HEIGHT","TimeRangeControls","heightPx","showTimeRangeSelector","showRefreshButton","showRefreshInterval","showCustomTimeRange","showZoomButtons","timePresets","timeRange","setTimeRange","refresh","refreshInterval","setRefreshInterval","showCustomTimeRangeValue","showZoomInOutButtons","timePresetsValue","height","undefined","some","option","push","handleRefreshIntervalChange","duration","fromDurationToMillis","strDuration","millis","seconds","minutes","hours","days","weeks","months","years","doubleTimeRange","newStart","newEnd","extendEndsBy","now","Date","Object","hasOwn","absVal","end","getTime","start","relVal","setTime","halfTimeRange","shrinkEndsBy","endIsAbsolute","setHalfTimeRange","setDoubleTimeRange","direction","spacing","timeOptions","onChange","description","zoomOut","aria-label","onClick","sx","zoomIn"],"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,OAAOA,iBAAiB,0BAA0B;AAClD,gDAAgD;AAChD,OAAOC,YAAY,oCAAoC;AACvD,gDAAgD;AAChD,OAAOC,aAAa,qCAAqC;AACzD,SAASC,KAAK,QAAQ,gBAAgB;AACtC,SACEC,qBAAqB,EACrBC,WAAW,EAEXC,iBAAiB,EACjBC,iBAAiB,EACjBC,uBAAuB,QAClB,yBAAyB;AAChC,SAA4CC,mBAAmB,QAA2B,mBAAmB;AAC7G,SAAuBC,WAAW,QAAQ,QAAQ;AAClD,SAASC,YAAY,QAAQ,kBAAkB;AAC/C,SACEC,YAAY,EACZC,6BAA6B,EAC7BC,0BAA0B,EAC1BC,uBAAuB,QAClB,gBAAgB;AAEvB,OAAO,MAAMC,mCAAiD;IAC5D;QAAEC,OAAO;YAAEC,cAAc;QAAK;QAAGC,SAAS;IAAM;IAChD;QAAEF,OAAO;YAAEC,cAAc;QAAK;QAAGC,SAAS;IAAK;IAC/C;QAAEF,OAAO;YAAEC,cAAc;QAAM;QAAGC,SAAS;IAAM;IACjD;QAAEF,OAAO;YAAEC,cAAc;QAAM;QAAGC,SAAS;IAAM;IACjD;QAAEF,OAAO;YAAEC,cAAc;QAAM;QAAGC,SAAS;IAAM;IACjD;QAAEF,OAAO;YAAEC,cAAc;QAAM;QAAGC,SAAS;IAAK;CACjD,CAAC;AAEF,MAAMC,iBAAiB;AAavB,OAAO,SAASC,kBAAkB,EAChCC,QAAQ,EACRC,wBAAwB,IAAI,EAC5BC,oBAAoB,IAAI,EACxBC,sBAAsB,IAAI,EAC1BC,mBAAmB,EACnBC,kBAAkB,IAAI,EACtBC,WAAW,EACY;IACvB,MAAM,EAAEC,SAAS,EAAEC,YAAY,EAAEC,OAAO,EAAEC,eAAe,EAAEC,kBAAkB,EAAE,GAAGrB;IAElF,MAAMsB,2BAA2BrB,8BAA8Ba;IAC/D,MAAMS,uBAAuBpB,wBAAwBY;IACrD,MAAMS,mBAAmBtB,2BAA2Bc;IAEpD,8DAA8D;IAC9D,MAAMS,SAASf,aAAagB,YAAYlB,iBAAiB,GAAGE,SAAS,EAAE,CAAC;IAExE,qEAAqE;IACrE,IACE,kBAAkBO,aAClB,CAACO,iBAAiBG,IAAI,CAAC,CAACC,SAAWA,OAAOvB,KAAK,CAACC,YAAY,KAAKW,SAAS,CAAC,eAAe,GAC1F;QACAO,iBAAiBK,IAAI,CAACjC,wBAAwBqB,SAAS,CAAC,eAAe;IACzE;IAEA,8EAA8E;IAC9E,MAAMa,8BAA8BhC,YAClC,CAACiC;QACCV,mBAAmBU;IACrB,GACA;QAACV;KAAmB;IAGtB,MAAMW,uBAAuB,CAACC;QAC5B,MAAMF,WAAWlC,oBAAoBoC;QACrC,MAAMC,SAEJ,AADA,6CAA6C;QAC5C,CAAA,AAACH,CAAAA,SAASI,OAAO,IAAI,CAAA,IACpB,AAACJ,CAAAA,SAASK,OAAO,IAAI,CAAA,IAAK,KAC1B,AAACL,CAAAA,SAASM,KAAK,IAAI,CAAA,IAAK,OACxB,AAACN,CAAAA,SAASO,IAAI,IAAI,CAAA,IAAK,QACvB,AAACP,CAAAA,SAASQ,KAAK,IAAI,CAAA,IAAK,IAAI,QAC5B,AAACR,CAAAA,SAASS,MAAM,IAAI,CAAA,IAAK,YAAY,QACrC,AAD6C,6CAA6C;QACzFT,CAAAA,SAASU,KAAK,IAAI,CAAA,IAAK,WAAW,KAAI,IAAK,4CAA4C;QAC1F,6CAA6C;QAC7C,MAAM,kBAAkB;QAC1B,OAAOP;IACT;IAEA,mGAAmG;IACnG,MAAMQ,kBAAkB;QACtB,IAAIC,UAAUC,QAAQC;QACtB,MAAMC,MAAM,IAAIC;QAChB,IAAIC,OAAOC,MAAM,CAAChC,WAAW,UAAU;YACrC,4BAA4B;YAC5B,MAAMiC,SAASjC;YACf4B,eAAe,AAACK,CAAAA,OAAOC,GAAG,CAACC,OAAO,KAAKF,OAAOG,KAAK,CAACD,OAAO,EAAC,IAAK,GAAG,gEAAgE;YACpIT,WAAW,IAAII,KAAKG,OAAOG,KAAK,CAACD,OAAO,KAAKP;YAC7CD,SAAS,IAAIG,KAAKG,OAAOC,GAAG,CAACC,OAAO,KAAKP;QAC3C,OAAO;YACL,4BAA4B;YAC5B,MAAMS,SAASrC;YACf4B,eAAeb,qBAAqBsB,OAAOhD,YAAY,IAAI;YAC3DsC,SAAS,OAAOU,OAAOH,GAAG,KAAK,cAAcL,MAAM,IAAIC,KAAKO,OAAOH,GAAG,CAACC,OAAO,KAAKP;YACnFF,WAAW,IAAII,KAAKH,OAAOQ,OAAO,KAAKP,eAAe;QACxD;QACA,IAAID,OAAOQ,OAAO,KAAKN,IAAIM,OAAO,IAAI;YACpC,2CAA2C;YAC3CR,SAASE;YACTH,SAASY,OAAO,CAACT,IAAIM,OAAO,KAAKP,eAAe;QAClD;QACA,IAAIF,SAASS,OAAO,KAAK,GAAG;YAC1BT,SAASY,OAAO,CAAC;QACnB;QACA,OAAO;YAAEF,OAAOV;YAAUQ,KAAKP;QAAO;IACxC;IAEA,kGAAkG;IAClG,MAAMY,gBAAgB;QACpB,IAAIb,UAAUC;QACd,IAAII,OAAOC,MAAM,CAAChC,WAAW,UAAU;YACrC,MAAMiC,SAASjC;YACf,MAAMwC,eAAe,AAACP,CAAAA,OAAOC,GAAG,CAACC,OAAO,KAAKF,OAAOG,KAAK,CAACD,OAAO,EAAC,IAAK;YACvET,WAAW,IAAII,KAAKG,OAAOG,KAAK,CAACD,OAAO,KAAKK;YAC7Cb,SAAS,IAAIG,KAAKG,OAAOC,GAAG,CAACC,OAAO,KAAKK;QAC3C,OAAO;YACL,MAAMH,SAASrC;YACf,MAAMwC,eAAezB,qBAAqBsB,OAAOhD,YAAY,IAAI,GAAG,8DAA8D;YAClI,MAAMoD,gBAAgB,OAAOJ,OAAOH,GAAG,KAAK;YAC5CP,SAASc,gBAAgB,IAAIX,KAAKO,OAAOH,GAAG,CAAEC,OAAO,KAAKK,gBAAgB,IAAIV;YAC9EJ,WAAW,IAAII,KAAKH,OAAOQ,OAAO,KAAKK,eAAe;QACxD;QACA,IAAId,SAASS,OAAO,MAAMR,OAAOQ,OAAO,KAAK,MAAM;YACjDT,SAASY,OAAO,CAACX,OAAOQ,OAAO,KAAK;QACtC;QACA,OAAO;YAAEC,OAAOV;YAAUQ,KAAKP;QAAO;IACxC;IAEA,MAAMe,mBAAmB,IAAYzC,aAAasC;IAClD,MAAMI,qBAAqB,IAAY1C,aAAawB;IAEpD,qBACE,MAACnD;QAAMsE,WAAU;QAAMC,SAAS;;YAC7BnD,uCACC,KAAChB;gBACCoE,aAAavC;gBACbnB,OAAOY;gBACP+C,UAAU9C;gBACVO,QAAQA;gBACRX,qBAAqBQ;;YAGxBC,sCACC,KAAC9B;gBAAYwE,aAAalE,aAAamE,OAAO;0BAC5C,cAAA,KAACxE;oBAAkByE,cAAYpE,aAAamE,OAAO;oBAAEE,SAASR;oBAAoBS,IAAI;wBAAE5C;oBAAO;8BAC7F,cAAA,KAACnC;;;YAINiC,sCACC,KAAC9B;gBAAYwE,aAAalE,aAAauE,MAAM;0BAC3C,cAAA,KAAC5E;oBAAkByE,cAAYpE,aAAauE,MAAM;oBAAEF,SAAST;oBAAkBU,IAAI;wBAAE5C;oBAAO;8BAC1F,cAAA,KAACpC;;;YAINuB,mCACC,KAACnB;gBAAYwE,aAAalE,aAAaoB,OAAO;0BAC5C,cAAA,KAACzB;oBAAkByE,cAAYpE,aAAaoB,OAAO;oBAAEiD,SAASjD;oBAASkD,IAAI;wBAAE5C;oBAAO;8BAClF,cAAA,KAACrC;;;YAINyB,qCACC,KAACpB;gBAAYwE,aAAalE,aAAaqB,eAAe;0BACpD,cAAA,KAAC5B;oBACCuE,aAAa3D;oBACbC,OAAOe;oBACP4C,UAAUlC;oBACVL,QAAQA;;;;;AAMpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariableEditorForm.d.ts","sourceRoot":"","sources":["../../../../src/components/Variables/VariableEditorForm/VariableEditorForm.tsx"],"names":[],"mappings":"AAaA,
|
|
1
|
+
{"version":3,"file":"VariableEditorForm.d.ts","sourceRoot":"","sources":["../../../../src/components/Variables/VariableEditorForm/VariableEditorForm.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAY,MAAM,OAAO,CAAC;AAEtE,OAAO,EAAE,kBAAkB,EAA0B,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAwTtF,UAAU,uBAAuB;IAC/B,yBAAyB,EAAE,kBAAkB,CAAC;IAC9C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,CAAC,GAAG,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC1C,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED,wBAAgB,kBAAkB,CAAC,EACjC,yBAAyB,EACzB,MAAM,EACN,OAAO,EACP,UAAU,EACV,cAAc,EACd,MAAM,EACN,OAAO,EACP,QAAQ,GACT,EAAE,uBAAuB,GAAG,YAAY,CAoMxC"}
|
|
@@ -11,15 +11,16 @@
|
|
|
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
|
|
15
|
-
import { Box, Typography, Switch, TextField, Grid, FormControlLabel, MenuItem, Stack,
|
|
14
|
+
import { useState } from 'react';
|
|
15
|
+
import { Box, Typography, Switch, TextField, Grid, FormControlLabel, MenuItem, Stack, Divider } from '@mui/material';
|
|
16
16
|
import { DiscardChangesConfirmationDialog, ErrorAlert, ErrorBoundary, FormActions } from '@perses-dev/components';
|
|
17
17
|
import { Controller, FormProvider, useForm, useFormContext, useWatch } from 'react-hook-form';
|
|
18
18
|
import { zodResolver } from '@hookform/resolvers/zod';
|
|
19
19
|
import { getSubmitText, getTitleAction } from '../../../utils';
|
|
20
|
-
import { VARIABLE_TYPES } from '../variable-model';
|
|
21
20
|
import { PluginEditor } from '../../PluginEditor';
|
|
22
21
|
import { useValidationSchemas } from '../../../context';
|
|
22
|
+
import { VARIABLE_TYPES } from '../variable-model';
|
|
23
|
+
import { useTimeRange } from '../../../runtime';
|
|
23
24
|
import { VariableListPreview, VariablePreview } from './VariablePreview';
|
|
24
25
|
function FallbackPreview() {
|
|
25
26
|
return /*#__PURE__*/ _jsx("div", {
|
|
@@ -95,10 +96,7 @@ function ListVariableEditorForm({ action, control }) {
|
|
|
95
96
|
/** We use `previewSpec` to know when to explicitly update the
|
|
96
97
|
* spec that will be used for preview. The reason why we do this is to avoid
|
|
97
98
|
* having to re-fetch the values when the user is still editing the spec.
|
|
98
|
-
*/ const
|
|
99
|
-
const refreshPreview = ()=>{
|
|
100
|
-
setPreviewSpec(form.getValues());
|
|
101
|
-
};
|
|
99
|
+
*/ const previewSpec = form.getValues();
|
|
102
100
|
const plugin = useWatch({
|
|
103
101
|
control,
|
|
104
102
|
name: 'spec.plugin'
|
|
@@ -118,6 +116,7 @@ function ListVariableEditorForm({ action, control }) {
|
|
|
118
116
|
if (values.spec.allowMultiple === undefined) {
|
|
119
117
|
form.setValue('spec.allowMultiple', false);
|
|
120
118
|
}
|
|
119
|
+
const { refresh } = useTimeRange();
|
|
121
120
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
122
121
|
children: [
|
|
123
122
|
/*#__PURE__*/ _jsx(Typography, {
|
|
@@ -136,53 +135,45 @@ function ListVariableEditorForm({ action, control }) {
|
|
|
136
135
|
previewSpec
|
|
137
136
|
],
|
|
138
137
|
children: /*#__PURE__*/ _jsx(VariableListPreview, {
|
|
139
|
-
definition: previewSpec
|
|
140
|
-
onRefresh: refreshPreview
|
|
138
|
+
definition: previewSpec
|
|
141
139
|
})
|
|
142
140
|
})
|
|
143
141
|
}) : /*#__PURE__*/ _jsx(VariablePreview, {
|
|
144
142
|
isLoading: true
|
|
145
143
|
}),
|
|
146
|
-
/*#__PURE__*/
|
|
147
|
-
children:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
value: {
|
|
166
|
-
selection: {
|
|
167
|
-
type: 'Variable',
|
|
168
|
-
kind: kind ?? 'StaticListVariable'
|
|
169
|
-
},
|
|
170
|
-
spec: pluginSpec ?? {
|
|
171
|
-
values: []
|
|
172
|
-
}
|
|
144
|
+
/*#__PURE__*/ _jsx(Stack, {
|
|
145
|
+
children: /*#__PURE__*/ _jsx(ErrorBoundary, {
|
|
146
|
+
FallbackComponent: ErrorAlert,
|
|
147
|
+
children: /*#__PURE__*/ _jsx(Controller, {
|
|
148
|
+
control: control,
|
|
149
|
+
name: "spec.plugin",
|
|
150
|
+
render: ({ field })=>{
|
|
151
|
+
return /*#__PURE__*/ _jsx(PluginEditor, {
|
|
152
|
+
postExecuteRunQuery: refresh,
|
|
153
|
+
withRunQueryButton: true,
|
|
154
|
+
width: "100%",
|
|
155
|
+
pluginTypes: [
|
|
156
|
+
'Variable'
|
|
157
|
+
],
|
|
158
|
+
pluginKindLabel: "Source",
|
|
159
|
+
value: {
|
|
160
|
+
selection: {
|
|
161
|
+
type: 'Variable',
|
|
162
|
+
kind: kind ?? 'StaticListVariable'
|
|
173
163
|
},
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
164
|
+
spec: pluginSpec ?? {}
|
|
165
|
+
},
|
|
166
|
+
isReadonly: action === 'read',
|
|
167
|
+
onChange: (v)=>{
|
|
168
|
+
field.onChange({
|
|
169
|
+
kind: v.selection.kind,
|
|
170
|
+
spec: v.spec
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
184
175
|
})
|
|
185
|
-
|
|
176
|
+
})
|
|
186
177
|
}),
|
|
187
178
|
/*#__PURE__*/ _jsx(Stack, {
|
|
188
179
|
children: /*#__PURE__*/ _jsx(Controller, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/Variables/VariableEditorForm/VariableEditorForm.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 React, { DispatchWithoutAction, ReactElement, useState } from 'react';\nimport {\n Box,\n Typography,\n Switch,\n TextField,\n Grid,\n FormControlLabel,\n MenuItem,\n Stack,\n ClickAwayListener,\n Divider,\n} from '@mui/material';\nimport { VariableDefinition, ListVariableDefinition, Action } from '@perses-dev/core';\nimport { DiscardChangesConfirmationDialog, ErrorAlert, ErrorBoundary, FormActions } from '@perses-dev/components';\nimport { Control, Controller, FormProvider, SubmitHandler, useForm, useFormContext, useWatch } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { getSubmitText, getTitleAction } from '../../../utils';\nimport { VARIABLE_TYPES } from '../variable-model';\nimport { PluginEditor } from '../../PluginEditor';\nimport { useValidationSchemas } from '../../../context';\nimport { VariableListPreview, VariablePreview } from './VariablePreview';\n\nfunction FallbackPreview(): ReactElement {\n return <div>Error previewing values</div>;\n}\n\ninterface KindVariableEditorFormProps {\n action: Action;\n control: Control<VariableDefinition>;\n}\n\nfunction TextVariableEditorForm({ action, control }: KindVariableEditorFormProps): ReactElement {\n return (\n <>\n <Typography py={1} variant=\"subtitle1\">\n Text Options\n </Typography>\n <Stack spacing={2}>\n <Controller\n control={control}\n name=\"spec.value\"\n render={({ field, fieldState }) => (\n <>\n <Box>\n <VariablePreview values={[field.value]} />\n </Box>\n <TextField\n {...field}\n label=\"Value\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n </>\n )}\n />\n <Controller\n control={control}\n name=\"spec.constant\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Constant\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n </Stack>\n </>\n );\n}\n\nfunction ListVariableEditorForm({ action, control }: KindVariableEditorFormProps): ReactElement {\n const form = useFormContext<VariableDefinition>();\n /** We use `previewSpec` to know when to explicitly update the\n * spec that will be used for preview. The reason why we do this is to avoid\n * having to re-fetch the values when the user is still editing the spec.\n */\n const [previewSpec, setPreviewSpec] = useState<ListVariableDefinition>(form.getValues() as ListVariableDefinition);\n const refreshPreview = (): void => {\n setPreviewSpec(form.getValues() as ListVariableDefinition);\n };\n\n const plugin = useWatch<VariableDefinition, 'spec.plugin'>({ control, name: 'spec.plugin' });\n const kind = plugin?.kind;\n const pluginSpec = plugin?.spec;\n\n const _allowAllValue = useWatch<VariableDefinition, 'spec.allowAllValue'>({\n control: control,\n name: 'spec.allowAllValue',\n });\n\n // When variable kind is selected we need to provide default values\n // TODO: check if react-hook-form has a better way to do this\n const values = form.getValues() as ListVariableDefinition;\n if (values.spec.allowAllValue === undefined) {\n form.setValue('spec.allowAllValue', false);\n }\n\n if (values.spec.allowMultiple === undefined) {\n form.setValue('spec.allowMultiple', false);\n }\n\n return (\n <>\n <Typography py={1} variant=\"subtitle1\">\n List Options\n </Typography>\n <Stack spacing={2} mb={2}>\n {kind ? (\n <Box>\n <ErrorBoundary FallbackComponent={FallbackPreview} resetKeys={[previewSpec]}>\n <VariableListPreview definition={previewSpec} onRefresh={refreshPreview} />\n </ErrorBoundary>\n </Box>\n ) : (\n <VariablePreview isLoading={true} />\n )}\n\n <Stack>\n {/** Hack?: Cool technique to refresh the preview to simulate onBlur event */}\n <ClickAwayListener onClickAway={() => refreshPreview()}>\n <Box />\n </ClickAwayListener>\n {/** **/}\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <Controller\n control={control}\n name=\"spec.plugin\"\n render={({ field }) => {\n return (\n <PluginEditor\n withRunQueryButton\n width=\"100%\"\n pluginTypes={['Variable']}\n pluginKindLabel=\"Source\"\n value={{\n selection: {\n type: 'Variable',\n kind: kind ?? 'StaticListVariable',\n },\n spec: pluginSpec ?? { values: [] },\n }}\n isReadonly={action === 'read'}\n onChange={(v) => {\n field.onChange({ kind: v.selection.kind, spec: v.spec });\n }}\n />\n );\n }}\n />\n </ErrorBoundary>\n </Stack>\n\n <Stack>\n <Controller\n control={control}\n name=\"spec.capturingRegexp\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n label=\"Capturing Regexp Filter\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n value={field.value ?? ''}\n onChange={(event) => {\n if (event.target.value === '') {\n field.onChange(undefined);\n } else {\n field.onChange(event);\n }\n }}\n helperText={\n fieldState.error?.message\n ? fieldState.error.message\n : 'Optional, if you want to filter on captured result.'\n }\n />\n )}\n />\n </Stack>\n\n <Stack>\n <Controller\n control={control}\n name=\"spec.sort\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n fullWidth\n label=\"Sort\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? 'none'}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n <MenuItem value=\"none\">None</MenuItem>\n <MenuItem value=\"alphabetical-asc\">Alphabetical, asc</MenuItem>\n <MenuItem value=\"alphabetical-desc\">Alphabetical, desc</MenuItem>\n <MenuItem value=\"numerical-asc\">Numerical, asc</MenuItem>\n <MenuItem value=\"numerical-desc\">Numerical, desc</MenuItem>\n <MenuItem value=\"alphabetical-ci-asc\">Alphabetical, case-insensitive, asc</MenuItem>\n <MenuItem value=\"alphabetical-ci-desc\">Alphabetical, case-insensitive, desc</MenuItem>\n </TextField>\n )}\n />\n </Stack>\n </Stack>\n\n <Divider />\n\n <Typography py={1} variant=\"subtitle1\">\n Dropdown Options\n </Typography>\n <Stack spacing=\"2\">\n <Stack>\n <Controller\n control={control}\n name=\"spec.allowMultiple\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Allow Multiple Values\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n <Typography variant=\"caption\">Enables multiple values to be selected at the same time</Typography>\n </Stack>\n <Stack>\n <Controller\n control={control}\n name=\"spec.allowAllValue\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Allow All option\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n <Typography mb={1} variant=\"caption\">\n Enables an option to include all variable values\n </Typography>\n {_allowAllValue && (\n <Controller\n control={control}\n name=\"spec.customAllValue\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Custom All Value\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={\n fieldState.error?.message\n ? fieldState.error.message\n : 'When All is selected, this value will be used'\n }\n value={field.value ?? ''}\n onChange={(event) => {\n if (event.target.value === '') {\n field.onChange(undefined);\n } else {\n field.onChange(event);\n }\n }}\n />\n )}\n />\n )}\n </Stack>\n </Stack>\n </>\n );\n}\n\ninterface VariableEditorFormProps {\n initialVariableDefinition: VariableDefinition;\n action: Action;\n isDraft: boolean;\n isReadonly?: boolean;\n onActionChange?: (action: Action) => void;\n onSave: (def: VariableDefinition) => void;\n onClose: () => void;\n onDelete?: DispatchWithoutAction;\n}\n\nexport function VariableEditorForm({\n initialVariableDefinition,\n action,\n isDraft,\n isReadonly,\n onActionChange,\n onSave,\n onClose,\n onDelete,\n}: VariableEditorFormProps): ReactElement {\n const [isDiscardDialogOpened, setDiscardDialogOpened] = useState<boolean>(false);\n const titleAction = getTitleAction(action, isDraft);\n const submitText = getSubmitText(action, isDraft);\n\n const { variableEditorSchema } = useValidationSchemas();\n const form = useForm<VariableDefinition>({\n resolver: zodResolver(variableEditorSchema),\n mode: 'onBlur',\n defaultValues: initialVariableDefinition,\n });\n\n const kind = useWatch({ control: form.control, name: 'kind' });\n\n function clearFormData(data: VariableDefinition): VariableDefinition {\n const result = { ...data };\n if (\n result.spec.display?.name === undefined &&\n result.spec.display?.description === undefined &&\n result.spec.display?.hidden === undefined\n ) {\n delete result.spec.display;\n }\n return result;\n }\n\n const processForm: SubmitHandler<VariableDefinition> = (data: VariableDefinition) => {\n // reset display attributes to undefined when empty, because we don't want to save empty strings\n onSave(clearFormData(data));\n };\n\n // When user click on cancel, several possibilities:\n // - create action: ask for discard approval\n // - update action: ask for discard approval if changed\n // - read action: don´t ask for discard approval\n function handleCancel(): void {\n if (JSON.stringify(initialVariableDefinition) !== JSON.stringify(clearFormData(form.getValues()))) {\n setDiscardDialogOpened(true);\n } else {\n onClose();\n }\n }\n\n return (\n <FormProvider {...form}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n padding: (theme) => theme.spacing(1, 2),\n borderBottom: (theme) => `1px solid ${theme.palette.divider}`,\n }}\n >\n <Typography variant=\"h2\">{titleAction} Variable</Typography>\n <FormActions\n action={action}\n submitText={submitText}\n isReadonly={isReadonly}\n isValid={form.formState.isValid}\n onActionChange={onActionChange}\n onSubmit={form.handleSubmit(processForm)}\n onDelete={onDelete}\n onCancel={handleCancel}\n />\n </Box>\n <Box padding={2} sx={{ overflowY: 'scroll' }}>\n <Grid container spacing={2} mb={2}>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"spec.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n required\n fullWidth\n label=\"Name\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n disabled: action === 'update' && !isDraft,\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"spec.display.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Display Label\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"spec.display.description\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Description\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"kind\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n fullWidth\n label=\"Type\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? 'TextVariable'}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n {VARIABLE_TYPES.map((v) => (\n <MenuItem key={v.kind} value={v.kind}>\n {v.label}\n </MenuItem>\n ))}\n </TextField>\n )}\n />\n </Grid>\n </Grid>\n\n <Divider />\n\n {kind === 'TextVariable' && (\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <TextVariableEditorForm action={action} control={form.control} />\n </ErrorBoundary>\n )}\n {kind === 'ListVariable' && (\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <ListVariableEditorForm action={action} control={form.control} />\n </ErrorBoundary>\n )}\n </Box>\n <DiscardChangesConfirmationDialog\n description=\"Are you sure you want to discard these changes? Changes cannot be recovered.\"\n isOpen={isDiscardDialogOpened}\n onCancel={() => {\n setDiscardDialogOpened(false);\n }}\n onDiscardChanges={() => {\n setDiscardDialogOpened(false);\n onClose();\n }}\n />\n </FormProvider>\n );\n}\n"],"names":["React","useState","Box","Typography","Switch","TextField","Grid","FormControlLabel","MenuItem","Stack","ClickAwayListener","Divider","DiscardChangesConfirmationDialog","ErrorAlert","ErrorBoundary","FormActions","Controller","FormProvider","useForm","useFormContext","useWatch","zodResolver","getSubmitText","getTitleAction","VARIABLE_TYPES","PluginEditor","useValidationSchemas","VariableListPreview","VariablePreview","FallbackPreview","div","TextVariableEditorForm","action","control","py","variant","spacing","name","render","field","fieldState","values","value","label","InputLabelProps","shrink","undefined","InputProps","readOnly","error","helperText","message","onChange","event","checked","ListVariableEditorForm","form","previewSpec","setPreviewSpec","getValues","refreshPreview","plugin","kind","pluginSpec","spec","_allowAllValue","allowAllValue","setValue","allowMultiple","mb","FallbackComponent","resetKeys","definition","onRefresh","isLoading","onClickAway","withRunQueryButton","width","pluginTypes","pluginKindLabel","selection","type","isReadonly","v","target","select","fullWidth","VariableEditorForm","initialVariableDefinition","isDraft","onActionChange","onSave","onClose","onDelete","isDiscardDialogOpened","setDiscardDialogOpened","titleAction","submitText","variableEditorSchema","resolver","mode","defaultValues","clearFormData","data","result","display","description","hidden","processForm","handleCancel","JSON","stringify","sx","alignItems","padding","theme","borderBottom","palette","divider","isValid","formState","onSubmit","handleSubmit","onCancel","overflowY","container","item","xs","required","disabled","map","isOpen","onDiscardChanges"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/Variables/VariableEditorForm/VariableEditorForm.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 { DispatchWithoutAction, ReactElement, useState } from 'react';\nimport { Box, Typography, Switch, TextField, Grid, FormControlLabel, MenuItem, Stack, Divider } from '@mui/material';\nimport { VariableDefinition, ListVariableDefinition, Action } from '@perses-dev/core';\nimport { DiscardChangesConfirmationDialog, ErrorAlert, ErrorBoundary, FormActions } from '@perses-dev/components';\nimport { Control, Controller, FormProvider, SubmitHandler, useForm, useFormContext, useWatch } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { getSubmitText, getTitleAction } from '../../../utils';\nimport { PluginEditor } from '../../PluginEditor';\nimport { useValidationSchemas } from '../../../context';\nimport { VARIABLE_TYPES } from '../variable-model';\nimport { useTimeRange } from '../../../runtime';\nimport { VariableListPreview, VariablePreview } from './VariablePreview';\n\nfunction FallbackPreview(): ReactElement {\n return <div>Error previewing values</div>;\n}\n\ninterface KindVariableEditorFormProps {\n action: Action;\n control: Control<VariableDefinition>;\n}\n\nfunction TextVariableEditorForm({ action, control }: KindVariableEditorFormProps): ReactElement {\n return (\n <>\n <Typography py={1} variant=\"subtitle1\">\n Text Options\n </Typography>\n <Stack spacing={2}>\n <Controller\n control={control}\n name=\"spec.value\"\n render={({ field, fieldState }) => (\n <>\n <Box>\n <VariablePreview values={[field.value]} />\n </Box>\n <TextField\n {...field}\n label=\"Value\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n </>\n )}\n />\n <Controller\n control={control}\n name=\"spec.constant\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Constant\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n </Stack>\n </>\n );\n}\n\nfunction ListVariableEditorForm({ action, control }: KindVariableEditorFormProps): ReactElement {\n const form = useFormContext<VariableDefinition>();\n /** We use `previewSpec` to know when to explicitly update the\n * spec that will be used for preview. The reason why we do this is to avoid\n * having to re-fetch the values when the user is still editing the spec.\n */\n const previewSpec = form.getValues() as ListVariableDefinition;\n\n const plugin = useWatch<VariableDefinition, 'spec.plugin'>({ control, name: 'spec.plugin' });\n const kind = plugin?.kind;\n const pluginSpec = plugin?.spec;\n\n const _allowAllValue = useWatch<VariableDefinition, 'spec.allowAllValue'>({\n control: control,\n name: 'spec.allowAllValue',\n });\n\n // When variable kind is selected we need to provide default values\n // TODO: check if react-hook-form has a better way to do this\n const values = form.getValues() as ListVariableDefinition;\n if (values.spec.allowAllValue === undefined) {\n form.setValue('spec.allowAllValue', false);\n }\n\n if (values.spec.allowMultiple === undefined) {\n form.setValue('spec.allowMultiple', false);\n }\n\n const { refresh } = useTimeRange();\n\n return (\n <>\n <Typography py={1} variant=\"subtitle1\">\n List Options\n </Typography>\n <Stack spacing={2} mb={2}>\n {kind ? (\n <Box>\n <ErrorBoundary FallbackComponent={FallbackPreview} resetKeys={[previewSpec]}>\n <VariableListPreview definition={previewSpec} />\n </ErrorBoundary>\n </Box>\n ) : (\n <VariablePreview isLoading={true} />\n )}\n\n <Stack>\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <Controller\n control={control}\n name=\"spec.plugin\"\n render={({ field }) => {\n return (\n <PluginEditor\n postExecuteRunQuery={refresh}\n withRunQueryButton\n width=\"100%\"\n pluginTypes={['Variable']}\n pluginKindLabel=\"Source\"\n value={{\n selection: {\n type: 'Variable',\n kind: kind ?? 'StaticListVariable',\n },\n spec: pluginSpec ?? {},\n }}\n isReadonly={action === 'read'}\n onChange={(v) => {\n field.onChange({ kind: v.selection.kind, spec: v.spec });\n }}\n />\n );\n }}\n />\n </ErrorBoundary>\n </Stack>\n\n <Stack>\n <Controller\n control={control}\n name=\"spec.capturingRegexp\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n label=\"Capturing Regexp Filter\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n value={field.value ?? ''}\n onChange={(event) => {\n if (event.target.value === '') {\n field.onChange(undefined);\n } else {\n field.onChange(event);\n }\n }}\n helperText={\n fieldState.error?.message\n ? fieldState.error.message\n : 'Optional, if you want to filter on captured result.'\n }\n />\n )}\n />\n </Stack>\n\n <Stack>\n <Controller\n control={control}\n name=\"spec.sort\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n fullWidth\n label=\"Sort\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? 'none'}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n <MenuItem value=\"none\">None</MenuItem>\n <MenuItem value=\"alphabetical-asc\">Alphabetical, asc</MenuItem>\n <MenuItem value=\"alphabetical-desc\">Alphabetical, desc</MenuItem>\n <MenuItem value=\"numerical-asc\">Numerical, asc</MenuItem>\n <MenuItem value=\"numerical-desc\">Numerical, desc</MenuItem>\n <MenuItem value=\"alphabetical-ci-asc\">Alphabetical, case-insensitive, asc</MenuItem>\n <MenuItem value=\"alphabetical-ci-desc\">Alphabetical, case-insensitive, desc</MenuItem>\n </TextField>\n )}\n />\n </Stack>\n </Stack>\n\n <Divider />\n\n <Typography py={1} variant=\"subtitle1\">\n Dropdown Options\n </Typography>\n <Stack spacing=\"2\">\n <Stack>\n <Controller\n control={control}\n name=\"spec.allowMultiple\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Allow Multiple Values\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n <Typography variant=\"caption\">Enables multiple values to be selected at the same time</Typography>\n </Stack>\n <Stack>\n <Controller\n control={control}\n name=\"spec.allowAllValue\"\n render={({ field }) => (\n <FormControlLabel\n label=\"Allow All option\"\n control={\n <Switch\n {...field}\n checked={!!field.value}\n readOnly={action === 'read'}\n value={field.value ?? false}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n }}\n />\n }\n />\n )}\n />\n <Typography mb={1} variant=\"caption\">\n Enables an option to include all variable values\n </Typography>\n {_allowAllValue && (\n <Controller\n control={control}\n name=\"spec.customAllValue\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Custom All Value\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={\n fieldState.error?.message\n ? fieldState.error.message\n : 'When All is selected, this value will be used'\n }\n value={field.value ?? ''}\n onChange={(event) => {\n if (event.target.value === '') {\n field.onChange(undefined);\n } else {\n field.onChange(event);\n }\n }}\n />\n )}\n />\n )}\n </Stack>\n </Stack>\n </>\n );\n}\n\ninterface VariableEditorFormProps {\n initialVariableDefinition: VariableDefinition;\n action: Action;\n isDraft: boolean;\n isReadonly?: boolean;\n onActionChange?: (action: Action) => void;\n onSave: (def: VariableDefinition) => void;\n onClose: () => void;\n onDelete?: DispatchWithoutAction;\n}\n\nexport function VariableEditorForm({\n initialVariableDefinition,\n action,\n isDraft,\n isReadonly,\n onActionChange,\n onSave,\n onClose,\n onDelete,\n}: VariableEditorFormProps): ReactElement {\n const [isDiscardDialogOpened, setDiscardDialogOpened] = useState<boolean>(false);\n const titleAction = getTitleAction(action, isDraft);\n const submitText = getSubmitText(action, isDraft);\n\n const { variableEditorSchema } = useValidationSchemas();\n const form = useForm<VariableDefinition>({\n resolver: zodResolver(variableEditorSchema),\n mode: 'onBlur',\n defaultValues: initialVariableDefinition,\n });\n\n const kind = useWatch({ control: form.control, name: 'kind' });\n\n function clearFormData(data: VariableDefinition): VariableDefinition {\n const result = { ...data };\n if (\n result.spec.display?.name === undefined &&\n result.spec.display?.description === undefined &&\n result.spec.display?.hidden === undefined\n ) {\n delete result.spec.display;\n }\n return result;\n }\n\n const processForm: SubmitHandler<VariableDefinition> = (data: VariableDefinition) => {\n // reset display attributes to undefined when empty, because we don't want to save empty strings\n onSave(clearFormData(data));\n };\n\n // When user click on cancel, several possibilities:\n // - create action: ask for discard approval\n // - update action: ask for discard approval if changed\n // - read action: don´t ask for discard approval\n function handleCancel(): void {\n if (JSON.stringify(initialVariableDefinition) !== JSON.stringify(clearFormData(form.getValues()))) {\n setDiscardDialogOpened(true);\n } else {\n onClose();\n }\n }\n\n return (\n <FormProvider {...form}>\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n padding: (theme) => theme.spacing(1, 2),\n borderBottom: (theme) => `1px solid ${theme.palette.divider}`,\n }}\n >\n <Typography variant=\"h2\">{titleAction} Variable</Typography>\n <FormActions\n action={action}\n submitText={submitText}\n isReadonly={isReadonly}\n isValid={form.formState.isValid}\n onActionChange={onActionChange}\n onSubmit={form.handleSubmit(processForm)}\n onDelete={onDelete}\n onCancel={handleCancel}\n />\n </Box>\n <Box padding={2} sx={{ overflowY: 'scroll' }}>\n <Grid container spacing={2} mb={2}>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"spec.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n required\n fullWidth\n label=\"Name\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n disabled: action === 'update' && !isDraft,\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"spec.display.name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Display Label\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={8}>\n <Controller\n control={form.control}\n name=\"spec.display.description\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n label=\"Description\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? ''}\n onChange={(event) => {\n field.onChange(event);\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={4}>\n <Controller\n control={form.control}\n name=\"kind\"\n render={({ field, fieldState }) => (\n <TextField\n select\n {...field}\n fullWidth\n label=\"Type\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n value={field.value ?? 'TextVariable'}\n onChange={(event) => {\n field.onChange(event);\n }}\n >\n {VARIABLE_TYPES.map((v) => (\n <MenuItem key={v.kind} value={v.kind}>\n {v.label}\n </MenuItem>\n ))}\n </TextField>\n )}\n />\n </Grid>\n </Grid>\n\n <Divider />\n\n {kind === 'TextVariable' && (\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <TextVariableEditorForm action={action} control={form.control} />\n </ErrorBoundary>\n )}\n {kind === 'ListVariable' && (\n <ErrorBoundary FallbackComponent={ErrorAlert}>\n <ListVariableEditorForm action={action} control={form.control} />\n </ErrorBoundary>\n )}\n </Box>\n <DiscardChangesConfirmationDialog\n description=\"Are you sure you want to discard these changes? Changes cannot be recovered.\"\n isOpen={isDiscardDialogOpened}\n onCancel={() => {\n setDiscardDialogOpened(false);\n }}\n onDiscardChanges={() => {\n setDiscardDialogOpened(false);\n onClose();\n }}\n />\n </FormProvider>\n );\n}\n"],"names":["useState","Box","Typography","Switch","TextField","Grid","FormControlLabel","MenuItem","Stack","Divider","DiscardChangesConfirmationDialog","ErrorAlert","ErrorBoundary","FormActions","Controller","FormProvider","useForm","useFormContext","useWatch","zodResolver","getSubmitText","getTitleAction","PluginEditor","useValidationSchemas","VARIABLE_TYPES","useTimeRange","VariableListPreview","VariablePreview","FallbackPreview","div","TextVariableEditorForm","action","control","py","variant","spacing","name","render","field","fieldState","values","value","label","InputLabelProps","shrink","undefined","InputProps","readOnly","error","helperText","message","onChange","event","checked","ListVariableEditorForm","form","previewSpec","getValues","plugin","kind","pluginSpec","spec","_allowAllValue","allowAllValue","setValue","allowMultiple","refresh","mb","FallbackComponent","resetKeys","definition","isLoading","postExecuteRunQuery","withRunQueryButton","width","pluginTypes","pluginKindLabel","selection","type","isReadonly","v","target","select","fullWidth","VariableEditorForm","initialVariableDefinition","isDraft","onActionChange","onSave","onClose","onDelete","isDiscardDialogOpened","setDiscardDialogOpened","titleAction","submitText","variableEditorSchema","resolver","mode","defaultValues","clearFormData","data","result","display","description","hidden","processForm","handleCancel","JSON","stringify","sx","alignItems","padding","theme","borderBottom","palette","divider","isValid","formState","onSubmit","handleSubmit","onCancel","overflowY","container","item","xs","required","disabled","map","isOpen","onDiscardChanges"],"mappings":"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"}
|
|
@@ -2,14 +2,12 @@ import { ReactElement } from 'react';
|
|
|
2
2
|
import { ListVariableDefinition } from '@perses-dev/core';
|
|
3
3
|
interface VariablePreviewProps {
|
|
4
4
|
values?: string[];
|
|
5
|
-
onRefresh?: () => void;
|
|
6
5
|
isLoading?: boolean;
|
|
7
6
|
error?: string;
|
|
8
7
|
}
|
|
9
8
|
export declare function VariablePreview(props: VariablePreviewProps): ReactElement;
|
|
10
9
|
interface VariableListPreviewProps {
|
|
11
10
|
definition: ListVariableDefinition;
|
|
12
|
-
onRefresh: () => void;
|
|
13
11
|
}
|
|
14
12
|
export declare function VariableListPreview(props: VariableListPreviewProps): ReactElement;
|
|
15
13
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VariablePreview.d.ts","sourceRoot":"","sources":["../../../../src/components/Variables/VariableEditorForm/VariablePreview.tsx"],"names":[],"mappings":"AAaA,OAAc,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"VariablePreview.d.ts","sourceRoot":"","sources":["../../../../src/components/Variables/VariableEditorForm/VariablePreview.tsx"],"names":[],"mappings":"AAaA,OAAc,EAAE,YAAY,EAAqB,MAAM,OAAO,CAAC;AAI/D,OAAO,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAM1D,UAAU,oBAAoB;IAC5B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,GAAG,YAAY,CA8CzE;AAED,UAAU,wBAAwB;IAChC,UAAU,EAAE,sBAAsB,CAAC;CACpC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,GAAG,YAAY,CAWjF"}
|
|
@@ -11,16 +11,15 @@
|
|
|
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 } from "react/jsx-runtime";
|
|
14
|
-
import React, { useState } from 'react';
|
|
14
|
+
import React, { useMemo, useState } from 'react';
|
|
15
15
|
import { Alert, Box, Card, Chip, CircularProgress, IconButton, Stack, Typography } from '@mui/material';
|
|
16
16
|
import { InfoTooltip, useSnackbar } from '@perses-dev/components';
|
|
17
|
-
import Refresh from 'mdi-material-ui/Refresh';
|
|
18
17
|
import Clipboard from 'mdi-material-ui/ClipboardOutline';
|
|
19
18
|
import { TOOLTIP_TEXT } from '../../../constants';
|
|
20
19
|
import { useListVariablePluginValues } from '../variable-model';
|
|
21
20
|
const DEFAULT_MAX_PREVIEW_VALUES = 50;
|
|
22
21
|
export function VariablePreview(props) {
|
|
23
|
-
const { values,
|
|
22
|
+
const { values, isLoading, error } = props;
|
|
24
23
|
const [maxValues, setMaxValues] = useState(DEFAULT_MAX_PREVIEW_VALUES);
|
|
25
24
|
const { infoSnackbar } = useSnackbar();
|
|
26
25
|
const showAll = ()=>{
|
|
@@ -42,14 +41,6 @@ export function VariablePreview(props) {
|
|
|
42
41
|
variant: "h4",
|
|
43
42
|
children: "Preview Values"
|
|
44
43
|
}),
|
|
45
|
-
onRefresh && /*#__PURE__*/ _jsx(InfoTooltip, {
|
|
46
|
-
description: TOOLTIP_TEXT.refreshVariableValues,
|
|
47
|
-
children: /*#__PURE__*/ _jsx(IconButton, {
|
|
48
|
-
onClick: onRefresh,
|
|
49
|
-
size: "small",
|
|
50
|
-
children: /*#__PURE__*/ _jsx(Refresh, {})
|
|
51
|
-
})
|
|
52
|
-
}),
|
|
53
44
|
/*#__PURE__*/ _jsx(InfoTooltip, {
|
|
54
45
|
description: TOOLTIP_TEXT.copyVariableValues,
|
|
55
46
|
children: /*#__PURE__*/ _jsx(IconButton, {
|
|
@@ -108,15 +99,19 @@ export function VariablePreview(props) {
|
|
|
108
99
|
});
|
|
109
100
|
}
|
|
110
101
|
export function VariableListPreview(props) {
|
|
111
|
-
const { definition
|
|
102
|
+
const { definition } = props;
|
|
112
103
|
const { data, isFetching, error } = useListVariablePluginValues(definition);
|
|
113
104
|
const errorMessage = error?.message;
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
105
|
+
const variablePreview = useMemo(()=>/*#__PURE__*/ _jsx(VariablePreview, {
|
|
106
|
+
values: data?.map((val)=>val.value) || [],
|
|
107
|
+
isLoading: isFetching,
|
|
108
|
+
error: errorMessage
|
|
109
|
+
}), [
|
|
110
|
+
errorMessage,
|
|
111
|
+
isFetching,
|
|
112
|
+
data
|
|
113
|
+
]);
|
|
114
|
+
return variablePreview;
|
|
120
115
|
}
|
|
121
116
|
|
|
122
117
|
//# sourceMappingURL=VariablePreview.js.map
|