@perses-dev/plugin-system 0.41.1 → 0.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/dist/cjs/components/DatasourceEditorForm/DatasourceEditorForm.js +26 -55
  2. package/dist/cjs/components/DatasourceSelect.js +22 -10
  3. package/dist/cjs/components/PanelSpecEditor/PanelSpecEditor.js +1 -0
  4. package/dist/cjs/components/PluginEditor/PluginEditor.js +2 -1
  5. package/dist/cjs/components/ProjectSelect.js +96 -0
  6. package/dist/cjs/components/TimeSeriesQueryEditor/TimeSeriesQueryEditor.js +14 -12
  7. package/dist/cjs/components/Variables/VariableEditorForm/VariableEditorForm.js +50 -2
  8. package/dist/cjs/components/Variables/VariableEditorForm/variable-editor-form-model.js +11 -8
  9. package/dist/cjs/components/index.js +1 -0
  10. package/dist/cjs/context/ProjectStoreProvider.js +78 -0
  11. package/dist/cjs/context/index.js +30 -0
  12. package/dist/cjs/context/query-params.js +49 -0
  13. package/dist/cjs/index.js +1 -0
  14. package/dist/cjs/model/index.js +1 -0
  15. package/dist/cjs/model/trace-queries.js +16 -0
  16. package/dist/cjs/runtime/DataQueriesProvider/DataQueriesProvider.js +17 -5
  17. package/dist/cjs/runtime/DataQueriesProvider/model.js +27 -7
  18. package/dist/cjs/runtime/TimeRangeProvider/TimeRangeProvider.js +27 -18
  19. package/dist/cjs/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.js +43 -0
  20. package/dist/cjs/runtime/TimeRangeProvider/index.js +1 -0
  21. package/dist/cjs/runtime/TimeRangeProvider/query-params.js +7 -39
  22. package/dist/cjs/runtime/TimeRangeProvider/refresh-interval.js +30 -0
  23. package/dist/cjs/runtime/datasources.js +3 -2
  24. package/dist/cjs/runtime/index.js +1 -0
  25. package/dist/cjs/runtime/trace-queries.js +59 -0
  26. package/dist/cjs/stories/shared-utils/decorators/WithPluginRegistry.js +2 -1
  27. package/dist/cjs/stories/shared-utils/decorators/WithPluginSystemDatasourceStore.js +12 -0
  28. package/dist/cjs/stories/shared-utils/decorators/WithTimeRange.js +2 -2
  29. package/dist/cjs/test/mock-data.js +26 -3
  30. package/dist/cjs/validation/role.js +85 -0
  31. package/dist/cjs/validation/rolebinding.js +55 -0
  32. package/dist/components/DatasourceEditorForm/DatasourceEditorForm.d.ts +7 -7
  33. package/dist/components/DatasourceEditorForm/DatasourceEditorForm.d.ts.map +1 -1
  34. package/dist/components/DatasourceEditorForm/DatasourceEditorForm.js +26 -16
  35. package/dist/components/DatasourceEditorForm/DatasourceEditorForm.js.map +1 -1
  36. package/dist/components/DatasourceSelect.d.ts +1 -0
  37. package/dist/components/DatasourceSelect.d.ts.map +1 -1
  38. package/dist/components/DatasourceSelect.js +22 -10
  39. package/dist/components/DatasourceSelect.js.map +1 -1
  40. package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts +1 -1
  41. package/dist/components/PanelSpecEditor/PanelSpecEditor.d.ts.map +1 -1
  42. package/dist/components/PanelSpecEditor/PanelSpecEditor.js +1 -0
  43. package/dist/components/PanelSpecEditor/PanelSpecEditor.js.map +1 -1
  44. package/dist/components/PluginEditor/PluginEditor.d.ts.map +1 -1
  45. package/dist/components/PluginEditor/PluginEditor.js +2 -1
  46. package/dist/components/PluginEditor/PluginEditor.js.map +1 -1
  47. package/dist/components/PluginEditor/plugin-editor-api.d.ts +1 -0
  48. package/dist/components/PluginEditor/plugin-editor-api.d.ts.map +1 -1
  49. package/dist/components/PluginEditor/plugin-editor-api.js.map +1 -1
  50. package/dist/components/PluginSpecEditor/PluginSpecEditor.d.ts +1 -0
  51. package/dist/components/PluginSpecEditor/PluginSpecEditor.d.ts.map +1 -1
  52. package/dist/components/PluginSpecEditor/PluginSpecEditor.js.map +1 -1
  53. package/dist/components/ProjectSelect.d.ts +15 -0
  54. package/dist/components/ProjectSelect.d.ts.map +1 -0
  55. package/dist/components/ProjectSelect.js +91 -0
  56. package/dist/components/ProjectSelect.js.map +1 -0
  57. package/dist/components/TimeSeriesQueryEditor/TimeSeriesQueryEditor.d.ts.map +1 -1
  58. package/dist/components/TimeSeriesQueryEditor/TimeSeriesQueryEditor.js +15 -13
  59. package/dist/components/TimeSeriesQueryEditor/TimeSeriesQueryEditor.js.map +1 -1
  60. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.d.ts +1 -2
  61. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.d.ts.map +1 -1
  62. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js +50 -2
  63. package/dist/components/Variables/VariableEditorForm/VariableEditorForm.js.map +1 -1
  64. package/dist/components/Variables/VariableEditorForm/variable-editor-form-model.d.ts +2 -1
  65. package/dist/components/Variables/VariableEditorForm/variable-editor-form-model.d.ts.map +1 -1
  66. package/dist/components/Variables/VariableEditorForm/variable-editor-form-model.js +11 -8
  67. package/dist/components/Variables/VariableEditorForm/variable-editor-form-model.js.map +1 -1
  68. package/dist/components/index.d.ts +1 -0
  69. package/dist/components/index.d.ts.map +1 -1
  70. package/dist/components/index.js +1 -0
  71. package/dist/components/index.js.map +1 -1
  72. package/dist/context/ProjectStoreProvider.d.ts +16 -0
  73. package/dist/context/ProjectStoreProvider.d.ts.map +1 -0
  74. package/dist/context/ProjectStoreProvider.js +56 -0
  75. package/dist/context/ProjectStoreProvider.js.map +1 -0
  76. package/dist/context/index.d.ts +2 -0
  77. package/dist/context/index.d.ts.map +1 -0
  78. package/dist/context/index.js +15 -0
  79. package/dist/context/index.js.map +1 -0
  80. package/dist/context/query-params.d.ts +5 -0
  81. package/dist/context/query-params.d.ts.map +1 -0
  82. package/dist/context/query-params.js +41 -0
  83. package/dist/context/query-params.js.map +1 -0
  84. package/dist/index.d.ts +1 -0
  85. package/dist/index.d.ts.map +1 -1
  86. package/dist/index.js +1 -0
  87. package/dist/index.js.map +1 -1
  88. package/dist/model/index.d.ts +1 -0
  89. package/dist/model/index.d.ts.map +1 -1
  90. package/dist/model/index.js +1 -0
  91. package/dist/model/index.js.map +1 -1
  92. package/dist/model/plugin-base.d.ts +1 -0
  93. package/dist/model/plugin-base.d.ts.map +1 -1
  94. package/dist/model/plugin-base.js.map +1 -1
  95. package/dist/model/plugins.d.ts +2 -0
  96. package/dist/model/plugins.d.ts.map +1 -1
  97. package/dist/model/plugins.js.map +1 -1
  98. package/dist/model/trace-queries.d.ts +18 -0
  99. package/dist/model/trace-queries.d.ts.map +1 -0
  100. package/dist/model/trace-queries.js +15 -0
  101. package/dist/model/trace-queries.js.map +1 -0
  102. package/dist/runtime/DataQueriesProvider/DataQueriesProvider.d.ts.map +1 -1
  103. package/dist/runtime/DataQueriesProvider/DataQueriesProvider.js +17 -5
  104. package/dist/runtime/DataQueriesProvider/DataQueriesProvider.js.map +1 -1
  105. package/dist/runtime/DataQueriesProvider/model.d.ts +1 -1
  106. package/dist/runtime/DataQueriesProvider/model.d.ts.map +1 -1
  107. package/dist/runtime/DataQueriesProvider/model.js +27 -7
  108. package/dist/runtime/DataQueriesProvider/model.js.map +1 -1
  109. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts +4 -3
  110. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.d.ts.map +1 -1
  111. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js +28 -19
  112. package/dist/runtime/TimeRangeProvider/TimeRangeProvider.js.map +1 -1
  113. package/dist/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.d.ts +9 -0
  114. package/dist/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.d.ts.map +1 -0
  115. package/dist/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.js +30 -0
  116. package/dist/runtime/TimeRangeProvider/TimeRangeProviderWithQueryParams.js.map +1 -0
  117. package/dist/runtime/TimeRangeProvider/index.d.ts +1 -0
  118. package/dist/runtime/TimeRangeProvider/index.d.ts.map +1 -1
  119. package/dist/runtime/TimeRangeProvider/index.js +1 -0
  120. package/dist/runtime/TimeRangeProvider/index.js.map +1 -1
  121. package/dist/runtime/TimeRangeProvider/query-params.d.ts +4 -4
  122. package/dist/runtime/TimeRangeProvider/query-params.d.ts.map +1 -1
  123. package/dist/runtime/TimeRangeProvider/query-params.js +8 -40
  124. package/dist/runtime/TimeRangeProvider/query-params.js.map +1 -1
  125. package/dist/runtime/TimeRangeProvider/refresh-interval.d.ts +7 -0
  126. package/dist/runtime/TimeRangeProvider/refresh-interval.d.ts.map +1 -0
  127. package/dist/runtime/TimeRangeProvider/refresh-interval.js +25 -0
  128. package/dist/runtime/TimeRangeProvider/refresh-interval.js.map +1 -0
  129. package/dist/runtime/datasources.d.ts +29 -2
  130. package/dist/runtime/datasources.d.ts.map +1 -1
  131. package/dist/runtime/datasources.js +3 -2
  132. package/dist/runtime/datasources.js.map +1 -1
  133. package/dist/runtime/index.d.ts +1 -0
  134. package/dist/runtime/index.d.ts.map +1 -1
  135. package/dist/runtime/index.js +1 -0
  136. package/dist/runtime/index.js.map +1 -1
  137. package/dist/runtime/trace-queries.d.ts +10 -0
  138. package/dist/runtime/trace-queries.d.ts.map +1 -0
  139. package/dist/runtime/trace-queries.js +47 -0
  140. package/dist/runtime/trace-queries.js.map +1 -0
  141. package/dist/stories/shared-utils/decorators/WithPluginRegistry.d.ts.map +1 -1
  142. package/dist/stories/shared-utils/decorators/WithPluginRegistry.js +2 -1
  143. package/dist/stories/shared-utils/decorators/WithPluginRegistry.js.map +1 -1
  144. package/dist/stories/shared-utils/decorators/WithPluginSystemDatasourceStore.d.ts.map +1 -1
  145. package/dist/stories/shared-utils/decorators/WithPluginSystemDatasourceStore.js +12 -0
  146. package/dist/stories/shared-utils/decorators/WithPluginSystemDatasourceStore.js.map +1 -1
  147. package/dist/stories/shared-utils/decorators/WithTimeRange.d.ts +2 -2
  148. package/dist/stories/shared-utils/decorators/WithTimeRange.d.ts.map +1 -1
  149. package/dist/stories/shared-utils/decorators/WithTimeRange.js +2 -2
  150. package/dist/stories/shared-utils/decorators/WithTimeRange.js.map +1 -1
  151. package/dist/test/mock-data.d.ts +2 -1
  152. package/dist/test/mock-data.d.ts.map +1 -1
  153. package/dist/test/mock-data.js +15 -0
  154. package/dist/test/mock-data.js.map +1 -1
  155. package/dist/utils/action.d.ts +1 -1
  156. package/dist/utils/action.d.ts.map +1 -1
  157. package/dist/utils/action.js.map +1 -1
  158. package/dist/validation/role.d.ts +228 -0
  159. package/dist/validation/role.d.ts.map +1 -0
  160. package/dist/validation/role.js +66 -0
  161. package/dist/validation/role.js.map +1 -0
  162. package/dist/validation/rolebinding.d.ts +137 -0
  163. package/dist/validation/rolebinding.d.ts.map +1 -0
  164. package/dist/validation/rolebinding.js +47 -0
  165. package/dist/validation/rolebinding.js.map +1 -0
  166. package/package.json +5 -4
@@ -0,0 +1,85 @@
1
+ // Copyright 2023 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ function _export(target, all) {
18
+ for(var name in all)Object.defineProperty(target, name, {
19
+ enumerable: true,
20
+ get: all[name]
21
+ });
22
+ }
23
+ _export(exports, {
24
+ roleValidationSchema: function() {
25
+ return roleValidationSchema;
26
+ },
27
+ globalRoleValidationSchema: function() {
28
+ return globalRoleValidationSchema;
29
+ },
30
+ rolesEditorValidationSchema: function() {
31
+ return rolesEditorValidationSchema;
32
+ }
33
+ });
34
+ const _zod = require("zod");
35
+ const _pluginsystem = require("@perses-dev/plugin-system");
36
+ const permissionValidationSchema = _zod.z.object({
37
+ // TODO: use SCOPE & ACTIONS constants
38
+ actions: _zod.z.array(_zod.z.enum([
39
+ '*',
40
+ 'create',
41
+ 'read',
42
+ 'update',
43
+ 'delete'
44
+ ])).nonempty('Must contains at least 1 action'),
45
+ scopes: _zod.z.array(_zod.z.enum([
46
+ '*',
47
+ 'Dashboard',
48
+ 'Datasource',
49
+ 'Folder',
50
+ 'GlobalDatasource',
51
+ 'GlobalRole',
52
+ 'GlobalRoleBinding',
53
+ 'GlobalSecret',
54
+ 'GlobalVariable',
55
+ 'Project',
56
+ 'Role',
57
+ 'RoleBinding',
58
+ 'Secret',
59
+ 'User',
60
+ 'Variable'
61
+ ])).nonempty('Must contains at least 1 scope')
62
+ });
63
+ const roleValidationSchema = _zod.z.object({
64
+ kind: _zod.z.literal('Role'),
65
+ metadata: _zod.z.object({
66
+ name: _pluginsystem.resourceIdValidationSchema,
67
+ project: _pluginsystem.resourceIdValidationSchema
68
+ }),
69
+ spec: _zod.z.object({
70
+ permissions: _zod.z.array(permissionValidationSchema)
71
+ })
72
+ });
73
+ const globalRoleValidationSchema = _zod.z.object({
74
+ kind: _zod.z.literal('GlobalRole'),
75
+ metadata: _zod.z.object({
76
+ name: _pluginsystem.resourceIdValidationSchema
77
+ }),
78
+ spec: _zod.z.object({
79
+ permissions: _zod.z.array(permissionValidationSchema)
80
+ })
81
+ });
82
+ const rolesEditorValidationSchema = _zod.z.discriminatedUnion('kind', [
83
+ roleValidationSchema,
84
+ globalRoleValidationSchema
85
+ ]);
@@ -0,0 +1,55 @@
1
+ // Copyright 2023 The Perses Authors
2
+ // Licensed under the Apache License, Version 2.0 (the "License");
3
+ // you may not use this file except in compliance with the License.
4
+ // You may obtain a copy of the License at
5
+ //
6
+ // http://www.apache.org/licenses/LICENSE-2.0
7
+ //
8
+ // Unless required by applicable law or agreed to in writing, software
9
+ // distributed under the License is distributed on an "AS IS" BASIS,
10
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ // See the License for the specific language governing permissions and
12
+ // limitations under the License.
13
+ "use strict";
14
+ Object.defineProperty(exports, "__esModule", {
15
+ value: true
16
+ });
17
+ Object.defineProperty(exports, "roleBindingsEditorValidationSchema", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return roleBindingsEditorValidationSchema;
21
+ }
22
+ });
23
+ const _zod = require("zod");
24
+ const _pluginsystem = require("@perses-dev/plugin-system");
25
+ const subjectValidationSchema = _zod.z.object({
26
+ kind: _zod.z.enum([
27
+ 'User'
28
+ ]),
29
+ name: _pluginsystem.resourceIdValidationSchema
30
+ });
31
+ const roleBindingValidationSchema = _zod.z.object({
32
+ kind: _zod.z.literal('RoleBinding'),
33
+ metadata: _zod.z.object({
34
+ name: _pluginsystem.resourceIdValidationSchema,
35
+ project: _pluginsystem.resourceIdValidationSchema
36
+ }),
37
+ spec: _zod.z.object({
38
+ role: _pluginsystem.resourceIdValidationSchema,
39
+ subjects: _zod.z.array(subjectValidationSchema).nonempty()
40
+ })
41
+ });
42
+ const globalRoleBindingValidationSchema = _zod.z.object({
43
+ kind: _zod.z.literal('GlobalRoleBinding'),
44
+ metadata: _zod.z.object({
45
+ name: _pluginsystem.resourceIdValidationSchema
46
+ }),
47
+ spec: _zod.z.object({
48
+ role: _pluginsystem.resourceIdValidationSchema,
49
+ subjects: _zod.z.array(subjectValidationSchema)
50
+ })
51
+ });
52
+ const roleBindingsEditorValidationSchema = _zod.z.discriminatedUnion('kind', [
53
+ roleBindingValidationSchema,
54
+ globalRoleBindingValidationSchema
55
+ ]);
@@ -1,15 +1,15 @@
1
- import { Datasource } from '@perses-dev/core';
2
- import { Dispatch, DispatchWithoutAction } from 'react';
3
- import { Action } from '../../utils';
4
- interface DatasourceEditorFormProps<T extends Datasource> {
5
- initialDatasource: T;
1
+ import { Action, DatasourceSpec } from '@perses-dev/core';
2
+ import { DispatchWithoutAction } from 'react';
3
+ interface DatasourceEditorFormProps {
4
+ initialName: string;
5
+ initialSpec: DatasourceSpec;
6
6
  initialAction: Action;
7
7
  isDraft: boolean;
8
8
  isReadonly?: boolean;
9
- onSave: Dispatch<T>;
9
+ onSave: (name: string, spec: DatasourceSpec) => void;
10
10
  onClose: DispatchWithoutAction;
11
11
  onDelete?: DispatchWithoutAction;
12
12
  }
13
- export declare function DatasourceEditorForm<T extends Datasource>(props: DatasourceEditorFormProps<T>): JSX.Element;
13
+ export declare function DatasourceEditorForm(props: DatasourceEditorFormProps): JSX.Element;
14
14
  export {};
15
15
  //# sourceMappingURL=DatasourceEditorForm.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DatasourceEditorForm.d.ts","sourceRoot":"","sources":["../../../src/components/DatasourceEditorForm/DatasourceEditorForm.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAW,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAc,EAAE,QAAQ,EAAE,qBAAqB,EAAyB,MAAM,OAAO,CAAC;AAKtF,OAAO,EAAE,MAAM,EAAiC,MAAM,aAAa,CAAC;AAsBpE,UAAU,yBAAyB,CAAC,CAAC,SAAS,UAAU;IACtD,iBAAiB,EAAE,CAAC,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;IACpB,OAAO,EAAE,qBAAqB,CAAC;IAC/B,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,UAAU,EAAE,KAAK,EAAE,yBAAyB,CAAC,CAAC,CAAC,eAiO7F"}
1
+ {"version":3,"file":"DatasourceEditorForm.d.ts","sourceRoot":"","sources":["../../../src/components/DatasourceEditorForm/DatasourceEditorForm.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,MAAM,EAAW,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEnE,OAAO,EAAE,qBAAqB,EAAyB,MAAM,OAAO,CAAC;AA2BrE,UAAU,yBAAyB;IACjC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,cAAc,CAAC;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACrD,OAAO,EAAE,qBAAqB,CAAC;IAC/B,QAAQ,CAAC,EAAE,qBAAqB,CAAC;CAClC;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,yBAAyB,eA2OpE"}
@@ -13,7 +13,7 @@
13
13
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
14
14
  import { useImmer } from 'use-immer';
15
15
  import { Box, Button, Divider, FormControlLabel, Grid, Stack, Switch, TextField, Typography } from '@mui/material';
16
- import React, { useCallback, useState } from 'react';
16
+ import { useCallback, useState } from 'react';
17
17
  import { DiscardChangesConfirmationDialog } from '@perses-dev/components';
18
18
  import { Controller, FormProvider, useForm } from 'react-hook-form';
19
19
  import { zodResolver } from '@hookform/resolvers/zod';
@@ -23,26 +23,26 @@ import { datasourceEditValidationSchema } from '../../validation';
23
23
  /**
24
24
  * This preprocessing ensures that we always have a defined object for the `display` property
25
25
  * @param datasource
26
- */ function getInitialState(datasource) {
27
- var _datasource_spec_display, _datasource_spec_display1;
28
- var _datasource_spec_display_name, _datasource_spec_display_description;
26
+ */ function getInitialState(name, spec) {
27
+ var _spec_display, _spec_display1;
28
+ var _spec_display_name, _spec_display_description;
29
29
  const patchedDisplay = {
30
- name: (_datasource_spec_display_name = (_datasource_spec_display = datasource.spec.display) === null || _datasource_spec_display === void 0 ? void 0 : _datasource_spec_display.name) !== null && _datasource_spec_display_name !== void 0 ? _datasource_spec_display_name : '',
31
- description: (_datasource_spec_display_description = (_datasource_spec_display1 = datasource.spec.display) === null || _datasource_spec_display1 === void 0 ? void 0 : _datasource_spec_display1.description) !== null && _datasource_spec_display_description !== void 0 ? _datasource_spec_display_description : ''
30
+ name: (_spec_display_name = (_spec_display = spec.display) === null || _spec_display === void 0 ? void 0 : _spec_display.name) !== null && _spec_display_name !== void 0 ? _spec_display_name : '',
31
+ description: (_spec_display_description = (_spec_display1 = spec.display) === null || _spec_display1 === void 0 ? void 0 : _spec_display1.description) !== null && _spec_display_description !== void 0 ? _spec_display_description : ''
32
32
  };
33
33
  return {
34
- ...datasource,
34
+ name: name,
35
35
  spec: {
36
- ...datasource.spec,
36
+ ...spec,
37
37
  display: patchedDisplay
38
38
  }
39
39
  };
40
40
  }
41
41
  export function DatasourceEditorForm(props) {
42
42
  var _state_spec_display, _state_spec_display1;
43
- const { initialDatasource , initialAction , isDraft , isReadonly , onSave , onClose , onDelete } = props;
44
- const patchedInitialDatasource = getInitialState(initialDatasource);
45
- const [state, setState] = useImmer(patchedInitialDatasource);
43
+ const { initialName , initialSpec , initialAction , isDraft , isReadonly , onSave , onClose , onDelete } = props;
44
+ const initialState = getInitialState(initialName, initialSpec);
45
+ const [state, setState] = useImmer(initialState);
46
46
  const [isDiscardDialogOpened, setDiscardDialogOpened] = useState(false);
47
47
  const [action, setAction] = useState(initialAction);
48
48
  const titleAction = getTitleAction(action, isDraft);
@@ -51,28 +51,38 @@ export function DatasourceEditorForm(props) {
51
51
  resolver: zodResolver(datasourceEditValidationSchema),
52
52
  mode: 'onBlur',
53
53
  defaultValues: {
54
- name: state.metadata.name,
54
+ name: state.name,
55
55
  title: (_state_spec_display = state.spec.display) === null || _state_spec_display === void 0 ? void 0 : _state_spec_display.name,
56
56
  description: (_state_spec_display1 = state.spec.display) === null || _state_spec_display1 === void 0 ? void 0 : _state_spec_display1.description,
57
57
  default: state.spec.default
58
58
  }
59
59
  });
60
60
  const processForm = ()=>{
61
- onSave(state);
61
+ var _state_spec_display;
62
+ // reset display name to undefined when empty, because we don't want an empty string as value
63
+ const name = (_state_spec_display = state.spec.display) === null || _state_spec_display === void 0 ? void 0 : _state_spec_display.name;
64
+ const finalDisplay = {
65
+ ...state.spec.display,
66
+ name: name ? name : undefined
67
+ };
68
+ onSave(state.name, {
69
+ ...state.spec,
70
+ display: finalDisplay
71
+ });
62
72
  };
63
73
  // When user click on cancel, several possibilities:
64
74
  // - create action: ask for discard approval
65
75
  // - update action: ask for discard approval if changed
66
76
  // - read action: don´t ask for discard approval
67
77
  const handleCancel = useCallback(()=>{
68
- if (JSON.stringify(patchedInitialDatasource) !== JSON.stringify(state)) {
78
+ if (JSON.stringify(initialState) !== JSON.stringify(state)) {
69
79
  setDiscardDialogOpened(true);
70
80
  } else {
71
81
  onClose();
72
82
  }
73
83
  }, [
74
84
  state,
75
- patchedInitialDatasource,
85
+ initialState,
76
86
  setDiscardDialogOpened,
77
87
  onClose
78
88
  ]);
@@ -188,7 +198,7 @@ export function DatasourceEditorForm(props) {
188
198
  onChange: (event)=>{
189
199
  field.onChange(event);
190
200
  setState((draft)=>{
191
- draft.metadata.name = event.target.value;
201
+ draft.name = event.target.value;
192
202
  });
193
203
  }
194
204
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/DatasourceEditorForm/DatasourceEditorForm.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 { useImmer } from 'use-immer';\nimport { Display, Datasource } from '@perses-dev/core';\nimport { Box, Button, Divider, FormControlLabel, Grid, Stack, Switch, TextField, Typography } from '@mui/material';\nimport React, { Dispatch, DispatchWithoutAction, useCallback, useState } from 'react';\nimport { DiscardChangesConfirmationDialog } from '@perses-dev/components';\nimport { Controller, FormProvider, SubmitHandler, useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { PluginEditor } from '../PluginEditor';\nimport { Action, getSubmitText, getTitleAction } from '../../utils';\nimport { datasourceEditValidationSchema, DatasourceEditValidationType } from '../../validation';\n\n/**\n * This preprocessing ensures that we always have a defined object for the `display` property\n * @param datasource\n */\nfunction getInitialState<T extends Datasource>(datasource: T): T {\n const patchedDisplay: Display = {\n name: datasource.spec.display?.name ?? '',\n description: datasource.spec.display?.description ?? '',\n };\n\n return {\n ...datasource,\n spec: {\n ...datasource.spec,\n display: patchedDisplay,\n },\n };\n}\n\ninterface DatasourceEditorFormProps<T extends Datasource> {\n initialDatasource: T;\n initialAction: Action;\n isDraft: boolean;\n isReadonly?: boolean;\n onSave: Dispatch<T>;\n onClose: DispatchWithoutAction;\n onDelete?: DispatchWithoutAction;\n}\n\nexport function DatasourceEditorForm<T extends Datasource>(props: DatasourceEditorFormProps<T>) {\n const { initialDatasource, initialAction, isDraft, isReadonly, onSave, onClose, onDelete } = props;\n\n const patchedInitialDatasource = getInitialState(initialDatasource);\n const [state, setState] = useImmer(patchedInitialDatasource);\n const [isDiscardDialogOpened, setDiscardDialogOpened] = useState<boolean>(false);\n const [action, setAction] = useState(initialAction);\n const titleAction = getTitleAction(action, isDraft);\n const submitText = getSubmitText(action, isDraft);\n\n const form = useForm<DatasourceEditValidationType>({\n resolver: zodResolver(datasourceEditValidationSchema),\n mode: 'onBlur',\n defaultValues: {\n name: state.metadata.name,\n title: state.spec.display?.name,\n description: state.spec.display?.description,\n default: state.spec.default,\n },\n });\n\n const processForm: SubmitHandler<DatasourceEditValidationType> = () => {\n onSave(state);\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 const handleCancel = useCallback(() => {\n if (JSON.stringify(patchedInitialDatasource) !== JSON.stringify(state)) {\n setDiscardDialogOpened(true);\n } else {\n onClose();\n }\n }, [state, patchedInitialDatasource, setDiscardDialogOpened, onClose]);\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} Datasource</Typography>\n <Stack direction=\"row\" spacing={1} sx={{ marginLeft: 'auto' }}>\n {action === 'read' ? (\n <>\n <Button disabled={isReadonly} variant=\"contained\" onClick={() => setAction('update')}>\n Edit\n </Button>\n <Button color=\"error\" disabled={isReadonly} variant=\"outlined\" onClick={onDelete}>\n Delete\n </Button>\n <Divider\n orientation=\"vertical\"\n flexItem\n sx={(theme) => ({\n borderColor: theme.palette.grey['500'],\n '&.MuiDivider-root': {\n marginLeft: 2,\n marginRight: 1,\n },\n })}\n />\n <Button color=\"secondary\" variant=\"outlined\" onClick={onClose}>\n Close\n </Button>\n </>\n ) : (\n <>\n <Button variant=\"contained\" disabled={!form.formState.isValid} onClick={form.handleSubmit(processForm)}>\n {submitText}\n </Button>\n <Button color=\"secondary\" variant=\"outlined\" onClick={handleCancel}>\n Cancel\n </Button>\n </>\n )}\n </Stack>\n </Box>\n <Box padding={2} sx={{ overflowY: 'scroll' }}>\n <Grid container spacing={2} mb={2}>\n <Grid item xs={4}>\n <Controller\n name=\"name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n required\n fullWidth\n name=\"name\"\n label=\"Name\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n disabled: action === 'update',\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n onChange={(event) => {\n field.onChange(event);\n setState((draft) => {\n draft.metadata.name = event.target.value;\n });\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={8}>\n <Controller\n name=\"title\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n name=\"title\"\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 onChange={(event) => {\n setState((draft) => {\n field.onChange(event);\n if (draft.spec.display) {\n draft.spec.display.name = event.target.value;\n }\n });\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={12}>\n <Controller\n name=\"description\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n name=\"description\"\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 onChange={(event) => {\n field.onChange(event);\n setState((draft) => {\n if (draft.spec.display) {\n draft.spec.display.description = event.target.value;\n }\n });\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={6} sx={{ paddingTop: '5px !important' }}>\n <Stack>\n <Controller\n name=\"default\"\n render={({ field }) => (\n <FormControlLabel\n {...field}\n control={\n <Switch\n checked={state.spec.default}\n readOnly={action === 'read'}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n setState((draft) => {\n draft.spec.default = event.target.checked;\n });\n }}\n />\n }\n label=\"Set as default\"\n />\n )}\n />\n <Typography variant=\"caption\">\n Whether this datasource should be the default {state.spec.plugin.kind} to be used\n </Typography>\n </Stack>\n </Grid>\n </Grid>\n <Divider />\n <Typography py={1} variant=\"h3\">\n Plugin Options\n </Typography>\n <PluginEditor\n width=\"100%\"\n pluginType=\"Datasource\"\n pluginKindLabel=\"Source\"\n value={state.spec.plugin}\n isReadonly={action === 'read'}\n onChange={(v) => {\n setState((draft) => {\n draft.spec.plugin = v;\n });\n }}\n />\n </Box>\n <DiscardChangesConfirmationDialog\n description=\"Are you sure you want to discard your changes? Changes cannot be recovered.\"\n isOpen={isDiscardDialogOpened}\n onCancel={() => setDiscardDialogOpened(false)}\n onDiscardChanges={() => {\n setDiscardDialogOpened(false);\n onClose();\n }}\n />\n </FormProvider>\n );\n}\n"],"names":["useImmer","Box","Button","Divider","FormControlLabel","Grid","Stack","Switch","TextField","Typography","React","useCallback","useState","DiscardChangesConfirmationDialog","Controller","FormProvider","useForm","zodResolver","PluginEditor","getSubmitText","getTitleAction","datasourceEditValidationSchema","getInitialState","datasource","patchedDisplay","name","spec","display","description","DatasourceEditorForm","props","state","initialDatasource","initialAction","isDraft","isReadonly","onSave","onClose","onDelete","patchedInitialDatasource","setState","isDiscardDialogOpened","setDiscardDialogOpened","action","setAction","titleAction","submitText","form","resolver","mode","defaultValues","metadata","title","default","processForm","handleCancel","JSON","stringify","sx","alignItems","padding","theme","spacing","borderBottom","palette","divider","variant","direction","marginLeft","disabled","onClick","color","orientation","flexItem","borderColor","grey","marginRight","formState","isValid","handleSubmit","overflowY","container","mb","item","xs","render","field","fieldState","required","fullWidth","label","InputLabelProps","shrink","undefined","InputProps","readOnly","error","helperText","message","onChange","event","draft","target","value","paddingTop","control","checked","plugin","kind","py","width","pluginType","pluginKindLabel","v","isOpen","onCancel","onDiscardChanges"],"mappings":"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"}
1
+ {"version":3,"sources":["../../../src/components/DatasourceEditorForm/DatasourceEditorForm.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 { useImmer } from 'use-immer';\nimport { Action, Display, DatasourceSpec } from '@perses-dev/core';\nimport { Box, Button, Divider, FormControlLabel, Grid, Stack, Switch, TextField, Typography } from '@mui/material';\nimport { DispatchWithoutAction, useCallback, useState } from 'react';\nimport { DiscardChangesConfirmationDialog } from '@perses-dev/components';\nimport { Controller, FormProvider, SubmitHandler, useForm } from 'react-hook-form';\nimport { zodResolver } from '@hookform/resolvers/zod';\nimport { PluginEditor } from '../PluginEditor';\nimport { getSubmitText, getTitleAction } from '../../utils';\nimport { datasourceEditValidationSchema, DatasourceEditValidationType } from '../../validation';\n\n/**\n * This preprocessing ensures that we always have a defined object for the `display` property\n * @param datasource\n */\nfunction getInitialState(name: string, spec: DatasourceSpec) {\n const patchedDisplay = {\n name: spec.display?.name ?? '',\n description: spec.display?.description ?? '',\n };\n\n return {\n name: name,\n spec: {\n ...spec,\n display: patchedDisplay,\n },\n };\n}\n\ninterface DatasourceEditorFormProps {\n initialName: string;\n initialSpec: DatasourceSpec;\n initialAction: Action;\n isDraft: boolean;\n isReadonly?: boolean;\n onSave: (name: string, spec: DatasourceSpec) => void;\n onClose: DispatchWithoutAction;\n onDelete?: DispatchWithoutAction;\n}\n\nexport function DatasourceEditorForm(props: DatasourceEditorFormProps) {\n const { initialName, initialSpec, initialAction, isDraft, isReadonly, onSave, onClose, onDelete } = props;\n\n const initialState = getInitialState(initialName, initialSpec);\n const [state, setState] = useImmer(initialState);\n const [isDiscardDialogOpened, setDiscardDialogOpened] = useState<boolean>(false);\n const [action, setAction] = useState(initialAction);\n const titleAction = getTitleAction(action, isDraft);\n const submitText = getSubmitText(action, isDraft);\n\n const form = useForm<DatasourceEditValidationType>({\n resolver: zodResolver(datasourceEditValidationSchema),\n mode: 'onBlur',\n defaultValues: {\n name: state.name,\n title: state.spec.display?.name,\n description: state.spec.display?.description,\n default: state.spec.default,\n },\n });\n\n const processForm: SubmitHandler<DatasourceEditValidationType> = () => {\n // reset display name to undefined when empty, because we don't want an empty string as value\n const name = state.spec.display?.name;\n const finalDisplay: Display | undefined = {\n ...state.spec.display,\n name: name ? name : undefined,\n };\n\n onSave(state.name, {\n ...state.spec,\n display: finalDisplay,\n });\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 const handleCancel = useCallback(() => {\n if (JSON.stringify(initialState) !== JSON.stringify(state)) {\n setDiscardDialogOpened(true);\n } else {\n onClose();\n }\n }, [state, initialState, setDiscardDialogOpened, onClose]);\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} Datasource</Typography>\n <Stack direction=\"row\" spacing={1} sx={{ marginLeft: 'auto' }}>\n {action === 'read' ? (\n <>\n <Button disabled={isReadonly} variant=\"contained\" onClick={() => setAction('update')}>\n Edit\n </Button>\n <Button color=\"error\" disabled={isReadonly} variant=\"outlined\" onClick={onDelete}>\n Delete\n </Button>\n <Divider\n orientation=\"vertical\"\n flexItem\n sx={(theme) => ({\n borderColor: theme.palette.grey['500'],\n '&.MuiDivider-root': {\n marginLeft: 2,\n marginRight: 1,\n },\n })}\n />\n <Button color=\"secondary\" variant=\"outlined\" onClick={onClose}>\n Close\n </Button>\n </>\n ) : (\n <>\n <Button variant=\"contained\" disabled={!form.formState.isValid} onClick={form.handleSubmit(processForm)}>\n {submitText}\n </Button>\n <Button color=\"secondary\" variant=\"outlined\" onClick={handleCancel}>\n Cancel\n </Button>\n </>\n )}\n </Stack>\n </Box>\n <Box padding={2} sx={{ overflowY: 'scroll' }}>\n <Grid container spacing={2} mb={2}>\n <Grid item xs={4}>\n <Controller\n name=\"name\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n required\n fullWidth\n name=\"name\"\n label=\"Name\"\n InputLabelProps={{ shrink: action === 'read' ? true : undefined }}\n InputProps={{\n disabled: action === 'update',\n readOnly: action === 'read',\n }}\n error={!!fieldState.error}\n helperText={fieldState.error?.message}\n onChange={(event) => {\n field.onChange(event);\n setState((draft) => {\n draft.name = event.target.value;\n });\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={8}>\n <Controller\n name=\"title\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n name=\"title\"\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 onChange={(event) => {\n setState((draft) => {\n field.onChange(event);\n if (draft.spec.display) {\n draft.spec.display.name = event.target.value;\n }\n });\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={12}>\n <Controller\n name=\"description\"\n render={({ field, fieldState }) => (\n <TextField\n {...field}\n fullWidth\n name=\"description\"\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 onChange={(event) => {\n field.onChange(event);\n setState((draft) => {\n if (draft.spec.display) {\n draft.spec.display.description = event.target.value;\n }\n });\n }}\n />\n )}\n />\n </Grid>\n <Grid item xs={6} sx={{ paddingTop: '5px !important' }}>\n <Stack>\n <Controller\n name=\"default\"\n render={({ field }) => (\n <FormControlLabel\n {...field}\n control={\n <Switch\n checked={state.spec.default}\n readOnly={action === 'read'}\n onChange={(event) => {\n if (action === 'read') return; // ReadOnly prop is not blocking user interaction...\n field.onChange(event);\n setState((draft) => {\n draft.spec.default = event.target.checked;\n });\n }}\n />\n }\n label=\"Set as default\"\n />\n )}\n />\n <Typography variant=\"caption\">\n Whether this datasource should be the default {state.spec.plugin.kind} to be used\n </Typography>\n </Stack>\n </Grid>\n </Grid>\n <Divider />\n <Typography py={1} variant=\"h3\">\n Plugin Options\n </Typography>\n <PluginEditor\n width=\"100%\"\n pluginType=\"Datasource\"\n pluginKindLabel=\"Source\"\n value={state.spec.plugin}\n isReadonly={action === 'read'}\n onChange={(v) => {\n setState((draft) => {\n draft.spec.plugin = v;\n });\n }}\n />\n </Box>\n <DiscardChangesConfirmationDialog\n description=\"Are you sure you want to discard your changes? Changes cannot be recovered.\"\n isOpen={isDiscardDialogOpened}\n onCancel={() => setDiscardDialogOpened(false)}\n onDiscardChanges={() => {\n setDiscardDialogOpened(false);\n onClose();\n }}\n />\n </FormProvider>\n );\n}\n"],"names":["useImmer","Box","Button","Divider","FormControlLabel","Grid","Stack","Switch","TextField","Typography","useCallback","useState","DiscardChangesConfirmationDialog","Controller","FormProvider","useForm","zodResolver","PluginEditor","getSubmitText","getTitleAction","datasourceEditValidationSchema","getInitialState","name","spec","patchedDisplay","display","description","DatasourceEditorForm","props","state","initialName","initialSpec","initialAction","isDraft","isReadonly","onSave","onClose","onDelete","initialState","setState","isDiscardDialogOpened","setDiscardDialogOpened","action","setAction","titleAction","submitText","form","resolver","mode","defaultValues","title","default","processForm","finalDisplay","undefined","handleCancel","JSON","stringify","sx","alignItems","padding","theme","spacing","borderBottom","palette","divider","variant","direction","marginLeft","disabled","onClick","color","orientation","flexItem","borderColor","grey","marginRight","formState","isValid","handleSubmit","overflowY","container","mb","item","xs","render","field","fieldState","required","fullWidth","label","InputLabelProps","shrink","InputProps","readOnly","error","helperText","message","onChange","event","draft","target","value","paddingTop","control","checked","plugin","kind","py","width","pluginType","pluginKindLabel","v","isOpen","onCancel","onDiscardChanges"],"mappings":"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"}
@@ -6,6 +6,7 @@ export interface DatasourceSelectProps extends Omit<SelectProps<string>, Omitted
6
6
  value: DatasourceSelector;
7
7
  onChange: (next: DatasourceSelector) => void;
8
8
  datasourcePluginKind: string;
9
+ project?: string;
9
10
  }
10
11
  /**
11
12
  * Displays a MUI input for selecting a Datasource of a particular kind. Note: The 'value' and `onChange` handler for
@@ -1 +1 @@
1
- {"version":3,"file":"DatasourceSelect.d.ts","sourceRoot":"","sources":["../../src/components/DatasourceSelect.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAU,WAAW,EAAiE,MAAM,eAAe,CAAC;AACnH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAMtD,aAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IACvF,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC7C,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,eAsF5D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,eAajG"}
1
+ {"version":3,"file":"DatasourceSelect.d.ts","sourceRoot":"","sources":["../../src/components/DatasourceSelect.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAU,WAAW,EAAiE,MAAM,eAAe,CAAC;AACnH,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAMtD,aAAK,eAAe,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,eAAe,CAAC;IACvF,KAAK,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC7C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,eAuF5D;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,eAajG"}
@@ -19,8 +19,8 @@ import { useListDatasourceSelectItems } from '../runtime';
19
19
  * Displays a MUI input for selecting a Datasource of a particular kind. Note: The 'value' and `onChange` handler for
20
20
  * the input deal with a `DatasourceSelector`.
21
21
  */ export function DatasourceSelect(props) {
22
- const { datasourcePluginKind , value , onChange , ...others } = props;
23
- const { data , isLoading } = useListDatasourceSelectItems(datasourcePluginKind);
22
+ const { datasourcePluginKind , value , project , onChange , ...others } = props;
23
+ const { data , isLoading } = useListDatasourceSelectItems(datasourcePluginKind, project);
24
24
  // Rebuild the group of the value if not provided
25
25
  const defaultValue = useMemo(()=>{
26
26
  var _flatMap_find;
@@ -37,6 +37,7 @@ import { useListDatasourceSelectItems } from '../runtime';
37
37
  ]);
38
38
  // Convert the datasource list into menu items with name/group?/value strings that the Select input can work with
39
39
  const menuItems = useMemo(()=>{
40
+ var _item_saved;
40
41
  return (data !== null && data !== void 0 ? data : []).map((itemGroup)=>({
41
42
  group: itemGroup.group,
42
43
  editLink: itemGroup.editLink,
@@ -44,6 +45,7 @@ import { useListDatasourceSelectItems } from '../runtime';
44
45
  name: item.name,
45
46
  overriding: item.overriding,
46
47
  overridden: item.overridden,
48
+ saved: (_item_saved = item.saved) !== null && _item_saved !== void 0 ? _item_saved : true,
47
49
  group: item.selector.group,
48
50
  value: selectorToOptionValue(item.selector)
49
51
  }))
@@ -76,7 +78,7 @@ import { useListDatasourceSelectItems } from '../runtime';
76
78
  /*#__PURE__*/ _jsx(Divider, {}, `${menuItemGroup.group}-divider`),
77
79
  ...menuItemGroup.items.map((menuItem)=>/*#__PURE__*/ _jsx(MenuItem, {
78
80
  value: menuItem.value,
79
- disabled: menuItem.overridden,
81
+ disabled: menuItem.overridden || !menuItem.saved,
80
82
  children: /*#__PURE__*/ _jsxs(Stack, {
81
83
  direction: "row",
82
84
  alignItems: "center",
@@ -90,6 +92,9 @@ import { useListDatasourceSelectItems } from '../runtime';
90
92
  overriding: menuItem.overriding
91
93
  })
92
94
  }),
95
+ !menuItem.saved && /*#__PURE__*/ _jsx(ListItemText, {
96
+ children: "Save the dashboard to enable this datasource"
97
+ }),
93
98
  /*#__PURE__*/ _jsx(ListItemText, {
94
99
  style: {
95
100
  textAlign: 'right'
@@ -131,8 +136,11 @@ export function DatasourceName(props) {
131
136
  }
132
137
  // Delimiter used to stringify/parse option values
133
138
  const OPTION_VALUE_DELIMITER = '_____';
134
- // Given a DatasourceSelector, returns a string value like `{kind}_____{name}` that can be used as a Select input value
135
- function selectorToOptionValue(selector) {
139
+ /**
140
+ * Given a DatasourceSelectItemSelector,
141
+ * returns a string value like `{kind}_____{group}_____{name}` that can be used as a Select input value.
142
+ * @param selector
143
+ */ function selectorToOptionValue(selector) {
136
144
  var _selector_group, _selector_name;
137
145
  return [
138
146
  selector.kind,
@@ -140,15 +148,19 @@ function selectorToOptionValue(selector) {
140
148
  (_selector_name = selector.name) !== null && _selector_name !== void 0 ? _selector_name : ''
141
149
  ].join(OPTION_VALUE_DELIMITER);
142
150
  }
143
- // Given an option value name like `{kind}_____{name}`, returns a DatasourceSelector
144
- function optionValueToSelector(optionValue) {
145
- const [kind, group, name] = optionValue.split(OPTION_VALUE_DELIMITER);
146
- if (kind === undefined || group === undefined || name === undefined) {
151
+ /**
152
+ * Given an option value name like `{kind}_____{group}_____{name}`,
153
+ * returns a DatasourceSelector to be used by the query data model.
154
+ * @param optionValue
155
+ */ function optionValueToSelector(optionValue) {
156
+ const words = optionValue.split(OPTION_VALUE_DELIMITER);
157
+ const kind = words[0];
158
+ const name = words[2];
159
+ if (kind === undefined || name === undefined) {
147
160
  throw new Error('Invalid optionValue string');
148
161
  }
149
162
  return {
150
163
  kind,
151
- group: group === '' ? undefined : group,
152
164
  name: name === '' ? undefined : name
153
165
  };
154
166
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/components/DatasourceSelect.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 OpenInNewIcon from 'mdi-material-ui/OpenInNew';\nimport { Select, SelectProps, MenuItem, Stack, Divider, ListItemText, Chip, IconButton, Box } from '@mui/material';\nimport { DatasourceSelector } from '@perses-dev/core';\nimport { useMemo } from 'react';\nimport { useListDatasourceSelectItems } from '../runtime';\n\n// Props on MUI Select 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 DatasourceSelectProps extends Omit<SelectProps<string>, OmittedMuiProps> {\n value: DatasourceSelector;\n onChange: (next: DatasourceSelector) => void;\n datasourcePluginKind: string;\n}\n\n/**\n * Displays a MUI input for selecting a Datasource of a particular kind. Note: The 'value' and `onChange` handler for\n * the input deal with a `DatasourceSelector`.\n */\nexport function DatasourceSelect(props: DatasourceSelectProps) {\n const { datasourcePluginKind, value, onChange, ...others } = props;\n const { data, isLoading } = useListDatasourceSelectItems(datasourcePluginKind);\n\n // Rebuild the group of the value if not provided\n const defaultValue = useMemo(() => {\n const group = (data ?? [])\n .flatMap((itemGroup) => itemGroup.items)\n .find((item) => {\n return value.kind === item.selector.kind && value.name === item.selector.name && !item.overridden;\n })?.selector.group;\n return { ...value, group };\n }, [value, data]);\n\n // Convert the datasource list into menu items with name/group?/value strings that the Select input can work with\n const menuItems = useMemo(() => {\n return (data ?? []).map((itemGroup) => ({\n group: itemGroup.group,\n editLink: itemGroup.editLink,\n items: itemGroup.items.map((item) => ({\n name: item.name,\n overriding: item.overriding,\n overridden: item.overridden,\n group: item.selector.group,\n value: selectorToOptionValue(item.selector),\n })),\n }));\n }, [data]);\n\n // While loading available values, just use an empty string so MUI select doesn't warn about values out of range\n const optionValue = isLoading ? '' : selectorToOptionValue(defaultValue);\n\n // When the user makes a selection, convert the string option value back to a DatasourceSelector\n const handleChange: SelectProps<string>['onChange'] = (e) => {\n const next = optionValueToSelector(e.target.value);\n onChange(next);\n };\n\n // We use a fake action event when we click on the action of the chip (hijack the \"delete\" feature).\n // This is because the href link action is on the `deleteIcon` property already, but the `onDelete` property\n // controls its visibility.\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const fakeActionEvent = () => {};\n\n // TODO:\n // - Does this need a loading indicator of some kind?\n // - The group's edit link is not clickable once selected.\n // - The group's edit link is disabled if datasource is overridden.\n // Ref: https://github.com/mui/material-ui/issues/36572\n return (\n <Select {...others} value={optionValue} onChange={handleChange}>\n {menuItems.map((menuItemGroup) => [\n <Divider key={`${menuItemGroup.group}-divider`} />,\n ...menuItemGroup.items.map((menuItem) => (\n <MenuItem key={menuItem.value} value={menuItem.value} disabled={menuItem.overridden}>\n <Stack direction=\"row\" alignItems=\"center\" justifyContent=\"space-between\" width=\"100%\">\n <ListItemText>\n <DatasourceName\n name={menuItem.name}\n overridden={menuItem.overridden}\n overriding={menuItem.overriding}\n />\n </ListItemText>\n <ListItemText style={{ textAlign: 'right' }}>\n {menuItemGroup.group && menuItemGroup.group.length > 0 && (\n <Chip\n disabled={false}\n label={menuItemGroup.group}\n size=\"small\"\n onDelete={menuItemGroup.editLink ? fakeActionEvent : undefined}\n deleteIcon={\n menuItemGroup.editLink ? (\n <IconButton href={menuItemGroup.editLink} target=\"_blank\">\n <OpenInNewIcon fontSize=\"small\" />\n </IconButton>\n ) : undefined\n }\n />\n )}\n </ListItemText>\n </Stack>\n </MenuItem>\n )),\n ])}\n </Select>\n );\n}\n\nexport function DatasourceName(props: { name: string; overridden?: boolean; overriding?: boolean }) {\n const { name, overridden, overriding } = props;\n return (\n <>\n {`${name} `}\n {!overridden && overriding && (\n <Box display=\"inline\" fontWeight=\"normal\" color={(theme) => theme.palette.primary.main}>\n (overriding)\n </Box>\n )}\n {overridden && '(overridden)'}\n </>\n );\n}\n\n// Delimiter used to stringify/parse option values\nconst OPTION_VALUE_DELIMITER = '_____';\n\n// Given a DatasourceSelector, returns a string value like `{kind}_____{name}` that can be used as a Select input value\nfunction selectorToOptionValue(selector: DatasourceSelector): string {\n return [selector.kind, selector.group ?? '', selector.name ?? ''].join(OPTION_VALUE_DELIMITER);\n}\n\n// Given an option value name like `{kind}_____{name}`, returns a DatasourceSelector\nfunction optionValueToSelector(optionValue: string): DatasourceSelector {\n const [kind, group, name] = optionValue.split(OPTION_VALUE_DELIMITER);\n if (kind === undefined || group === undefined || name === undefined) {\n throw new Error('Invalid optionValue string');\n }\n return {\n kind,\n group: group === '' ? undefined : group,\n name: name === '' ? undefined : name,\n };\n}\n"],"names":["OpenInNewIcon","Select","MenuItem","Stack","Divider","ListItemText","Chip","IconButton","Box","useMemo","useListDatasourceSelectItems","DatasourceSelect","props","datasourcePluginKind","value","onChange","others","data","isLoading","defaultValue","group","flatMap","itemGroup","items","find","item","kind","selector","name","overridden","menuItems","map","editLink","overriding","selectorToOptionValue","optionValue","handleChange","e","next","optionValueToSelector","target","fakeActionEvent","menuItemGroup","menuItem","disabled","direction","alignItems","justifyContent","width","DatasourceName","style","textAlign","length","label","size","onDelete","undefined","deleteIcon","href","fontSize","display","fontWeight","color","theme","palette","primary","main","OPTION_VALUE_DELIMITER","join","split","Error"],"mappings":"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"}
1
+ {"version":3,"sources":["../../src/components/DatasourceSelect.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 OpenInNewIcon from 'mdi-material-ui/OpenInNew';\nimport { Select, SelectProps, MenuItem, Stack, Divider, ListItemText, Chip, IconButton, Box } from '@mui/material';\nimport { DatasourceSelector } from '@perses-dev/core';\nimport { useMemo } from 'react';\nimport { DatasourceSelectItemSelector, useListDatasourceSelectItems } from '../runtime';\n\n// Props on MUI Select 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 DatasourceSelectProps extends Omit<SelectProps<string>, OmittedMuiProps> {\n value: DatasourceSelector;\n onChange: (next: DatasourceSelector) => void;\n datasourcePluginKind: string;\n project?: string;\n}\n\n/**\n * Displays a MUI input for selecting a Datasource of a particular kind. Note: The 'value' and `onChange` handler for\n * the input deal with a `DatasourceSelector`.\n */\nexport function DatasourceSelect(props: DatasourceSelectProps) {\n const { datasourcePluginKind, value, project, onChange, ...others } = props;\n const { data, isLoading } = useListDatasourceSelectItems(datasourcePluginKind, project);\n // Rebuild the group of the value if not provided\n const defaultValue = useMemo(() => {\n const group = (data ?? [])\n .flatMap((itemGroup) => itemGroup.items)\n .find((item) => {\n return value.kind === item.selector.kind && value.name === item.selector.name && !item.overridden;\n })?.selector.group;\n return { ...value, group };\n }, [value, data]);\n\n // Convert the datasource list into menu items with name/group?/value strings that the Select input can work with\n const menuItems = useMemo(() => {\n return (data ?? []).map((itemGroup) => ({\n group: itemGroup.group,\n editLink: itemGroup.editLink,\n items: itemGroup.items.map((item) => ({\n name: item.name,\n overriding: item.overriding,\n overridden: item.overridden,\n saved: item.saved ?? true,\n group: item.selector.group,\n value: selectorToOptionValue(item.selector),\n })),\n }));\n }, [data]);\n\n // While loading available values, just use an empty string so MUI select doesn't warn about values out of range\n const optionValue = isLoading ? '' : selectorToOptionValue(defaultValue);\n\n // When the user makes a selection, convert the string option value back to a DatasourceSelector\n const handleChange: SelectProps<string>['onChange'] = (e) => {\n const next = optionValueToSelector(e.target.value);\n onChange(next);\n };\n\n // We use a fake action event when we click on the action of the chip (hijack the \"delete\" feature).\n // This is because the href link action is on the `deleteIcon` property already, but the `onDelete` property\n // controls its visibility.\n // eslint-disable-next-line @typescript-eslint/no-empty-function\n const fakeActionEvent = () => {};\n\n // TODO:\n // - Does this need a loading indicator of some kind?\n // - The group's edit link is not clickable once selected.\n // - The group's edit link is disabled if datasource is overridden.\n // Ref: https://github.com/mui/material-ui/issues/36572\n return (\n <Select {...others} value={optionValue} onChange={handleChange}>\n {menuItems.map((menuItemGroup) => [\n <Divider key={`${menuItemGroup.group}-divider`} />,\n ...menuItemGroup.items.map((menuItem) => (\n <MenuItem key={menuItem.value} value={menuItem.value} disabled={menuItem.overridden || !menuItem.saved}>\n <Stack direction=\"row\" alignItems=\"center\" justifyContent=\"space-between\" width=\"100%\">\n <ListItemText>\n <DatasourceName\n name={menuItem.name}\n overridden={menuItem.overridden}\n overriding={menuItem.overriding}\n />\n </ListItemText>\n {!menuItem.saved && <ListItemText>Save the dashboard to enable this datasource</ListItemText>}\n <ListItemText style={{ textAlign: 'right' }}>\n {menuItemGroup.group && menuItemGroup.group.length > 0 && (\n <Chip\n disabled={false}\n label={menuItemGroup.group}\n size=\"small\"\n onDelete={menuItemGroup.editLink ? fakeActionEvent : undefined}\n deleteIcon={\n menuItemGroup.editLink ? (\n <IconButton href={menuItemGroup.editLink} target=\"_blank\">\n <OpenInNewIcon fontSize=\"small\" />\n </IconButton>\n ) : undefined\n }\n />\n )}\n </ListItemText>\n </Stack>\n </MenuItem>\n )),\n ])}\n </Select>\n );\n}\n\nexport function DatasourceName(props: { name: string; overridden?: boolean; overriding?: boolean }) {\n const { name, overridden, overriding } = props;\n return (\n <>\n {`${name} `}\n {!overridden && overriding && (\n <Box display=\"inline\" fontWeight=\"normal\" color={(theme) => theme.palette.primary.main}>\n (overriding)\n </Box>\n )}\n {overridden && '(overridden)'}\n </>\n );\n}\n\n// Delimiter used to stringify/parse option values\nconst OPTION_VALUE_DELIMITER = '_____';\n\n/**\n * Given a DatasourceSelectItemSelector,\n * returns a string value like `{kind}_____{group}_____{name}` that can be used as a Select input value.\n * @param selector\n */\nfunction selectorToOptionValue(selector: DatasourceSelectItemSelector): string {\n return [selector.kind, selector.group ?? '', selector.name ?? ''].join(OPTION_VALUE_DELIMITER);\n}\n\n/**\n * Given an option value name like `{kind}_____{group}_____{name}`,\n * returns a DatasourceSelector to be used by the query data model.\n * @param optionValue\n */\nfunction optionValueToSelector(optionValue: string): DatasourceSelector {\n const words = optionValue.split(OPTION_VALUE_DELIMITER);\n const kind = words[0];\n const name = words[2];\n if (kind === undefined || name === undefined) {\n throw new Error('Invalid optionValue string');\n }\n return {\n kind,\n name: name === '' ? undefined : name,\n };\n}\n"],"names":["OpenInNewIcon","Select","MenuItem","Stack","Divider","ListItemText","Chip","IconButton","Box","useMemo","useListDatasourceSelectItems","DatasourceSelect","props","datasourcePluginKind","value","project","onChange","others","data","isLoading","defaultValue","group","flatMap","itemGroup","items","find","item","kind","selector","name","overridden","menuItems","map","editLink","overriding","saved","selectorToOptionValue","optionValue","handleChange","e","next","optionValueToSelector","target","fakeActionEvent","menuItemGroup","menuItem","disabled","direction","alignItems","justifyContent","width","DatasourceName","style","textAlign","length","label","size","onDelete","undefined","deleteIcon","href","fontSize","display","fontWeight","color","theme","palette","primary","main","OPTION_VALUE_DELIMITER","join","words","split","Error"],"mappings":"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"}
@@ -4,7 +4,7 @@ export interface PanelSpecEditorProps {
4
4
  panelDefinition: PanelDefinition;
5
5
  onQueriesChange: (queries: QueryDefinition[]) => void;
6
6
  onPluginSpecChange: (spec: UnknownSpec) => void;
7
- onJSONChange: (panelDefinition: PanelDefinition) => void;
7
+ onJSONChange: (panelDefinitionStr: string) => void;
8
8
  }
9
9
  export declare function PanelSpecEditor(props: PanelSpecEditorProps): JSX.Element | null;
10
10
  //# sourceMappingURL=PanelSpecEditor.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"PanelSpecEditor.d.ts","sourceRoot":"","sources":["../../../src/components/PanelSpecEditor/PanelSpecEditor.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAMjF,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,eAAe,CAAC;IACjC,eAAe,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IACtD,kBAAkB,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,YAAY,EAAE,CAAC,eAAe,EAAE,eAAe,KAAK,IAAI,CAAC;CAC1D;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,sBA0C1D"}
1
+ {"version":3,"file":"PanelSpecEditor.d.ts","sourceRoot":"","sources":["../../../src/components/PanelSpecEditor/PanelSpecEditor.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAMjF,MAAM,WAAW,oBAAoB;IACnC,eAAe,EAAE,eAAe,CAAC;IACjC,eAAe,EAAE,CAAC,OAAO,EAAE,eAAe,EAAE,KAAK,IAAI,CAAC;IACtD,kBAAkB,EAAE,CAAC,IAAI,EAAE,WAAW,KAAK,IAAI,CAAC;IAChD,YAAY,EAAE,CAAC,kBAAkB,EAAE,MAAM,KAAK,IAAI,CAAC;CACpD;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,sBA6C1D"}
@@ -57,6 +57,7 @@ export function PanelSpecEditor(props) {
57
57
  tabs.push({
58
58
  label: 'JSON',
59
59
  content: /*#__PURE__*/ _jsx(JSONEditor, {
60
+ maxHeight: "80vh",
60
61
  value: panelDefinition,
61
62
  onChange: onJSONChange
62
63
  })
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/PanelSpecEditor/PanelSpecEditor.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 { ErrorAlert, JSONEditor } from '@perses-dev/components';\nimport { PanelDefinition, QueryDefinition, UnknownSpec } from '@perses-dev/core';\nimport { usePlugin } from '../../runtime';\nimport { PanelPlugin } from '../../model';\nimport { OptionsEditorTabsProps, OptionsEditorTabs } from '../OptionsEditorTabs';\nimport { TimeSeriesQueryEditor } from '../TimeSeriesQueryEditor';\n\nexport interface PanelSpecEditorProps {\n panelDefinition: PanelDefinition;\n onQueriesChange: (queries: QueryDefinition[]) => void;\n onPluginSpecChange: (spec: UnknownSpec) => void;\n onJSONChange: (panelDefinition: PanelDefinition) => void;\n}\n\nexport function PanelSpecEditor(props: PanelSpecEditorProps) {\n const { panelDefinition, onJSONChange, onQueriesChange, onPluginSpecChange } = props;\n const { kind } = panelDefinition.spec.plugin;\n const { data: plugin, isLoading, error } = usePlugin('Panel', kind);\n\n if (error) {\n return <ErrorAlert error={error} />;\n }\n\n // TODO: Proper loading indicator\n if (isLoading) {\n return null;\n }\n\n if (plugin === undefined) {\n throw new Error(`Missing implementation for panel plugin with kind '${kind}'`);\n }\n\n const { panelOptionsEditorComponents, hideQueryEditor } = plugin as PanelPlugin;\n let tabs: OptionsEditorTabsProps['tabs'] = [];\n\n if (!hideQueryEditor) {\n // Since we only support TimeSeriesQuery for now, we will always show a TimeSeriesQueryEditor\n tabs.push({\n label: 'Query',\n content: <TimeSeriesQueryEditor queries={panelDefinition.spec.queries ?? []} onChange={onQueriesChange} />,\n });\n }\n\n if (panelOptionsEditorComponents !== undefined) {\n tabs = tabs.concat(\n panelOptionsEditorComponents.map(({ label, content: OptionsEditorComponent }) => ({\n label,\n content: <OptionsEditorComponent value={panelDefinition.spec.plugin.spec} onChange={onPluginSpecChange} />,\n }))\n );\n }\n\n // always show json editor by default\n tabs.push({ label: 'JSON', content: <JSONEditor value={panelDefinition} onChange={onJSONChange} /> });\n\n return <OptionsEditorTabs key={tabs.length} tabs={tabs} />;\n}\n"],"names":["ErrorAlert","JSONEditor","usePlugin","OptionsEditorTabs","TimeSeriesQueryEditor","PanelSpecEditor","props","panelDefinition","onJSONChange","onQueriesChange","onPluginSpecChange","kind","spec","plugin","data","isLoading","error","undefined","Error","panelOptionsEditorComponents","hideQueryEditor","tabs","push","label","content","queries","onChange","concat","map","OptionsEditorComponent","value","length"],"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,UAAU,EAAEC,UAAU,QAAQ,yBAAyB;AAEhE,SAASC,SAAS,QAAQ,gBAAgB;AAE1C,SAAiCC,iBAAiB,QAAQ,uBAAuB;AACjF,SAASC,qBAAqB,QAAQ,2BAA2B;AASjE,OAAO,SAASC,gBAAgBC,KAA2B;IACzD,MAAM,EAAEC,gBAAe,EAAEC,aAAY,EAAEC,gBAAe,EAAEC,mBAAkB,EAAE,GAAGJ;IAC/E,MAAM,EAAEK,KAAI,EAAE,GAAGJ,gBAAgBK,KAAKC;IACtC,MAAM,EAAEC,MAAMD,OAAM,EAAEE,UAAS,EAAEC,MAAK,EAAE,GAAGd,UAAU,SAASS;IAE9D,IAAIK,OAAO;QACT,qBAAO,KAAChB;YAAWgB,OAAOA;;IAC5B;IAEA,iCAAiC;IACjC,IAAID,WAAW;QACb,OAAO;IACT;IAEA,IAAIF,WAAWI,WAAW;QACxB,MAAM,IAAIC,MAAM,CAAC,mDAAmD,EAAEP,KAAK,CAAC,CAAC;IAC/E;IAEA,MAAM,EAAEQ,6BAA4B,EAAEC,gBAAe,EAAE,GAAGP;IAC1D,IAAIQ,OAAuC,EAAE;IAE7C,IAAI,CAACD,iBAAiB;YAIuBb;QAH3C,6FAA6F;QAC7Fc,KAAKC,KAAK;YACRC,OAAO;YACPC,uBAAS,KAACpB;gBAAsBqB,SAASlB,CAAAA,gCAAAA,gBAAgBK,KAAKa,qBAArBlB,2CAAAA,gCAAgC,EAAE;gBAAEmB,UAAUjB;;QACzF;IACF;IAEA,IAAIU,iCAAiCF,WAAW;QAC9CI,OAAOA,KAAKM,OACVR,6BAA6BS,IAAI,CAAC,EAAEL,MAAK,EAAEC,SAASK,uBAAsB,EAAE,GAAM,CAAA;gBAChFN;gBACAC,uBAAS,KAACK;oBAAuBC,OAAOvB,gBAAgBK,KAAKC,OAAOD;oBAAMc,UAAUhB;;YACtF,CAAA;IAEJ;IAEA,qCAAqC;IACrCW,KAAKC,KAAK;QAAEC,OAAO;QAAQC,uBAAS,KAACvB;YAAW6B,OAAOvB;YAAiBmB,UAAUlB;;IAAiB;IAEnG,qBAAO,KAACL;QAAoCkB,MAAMA;OAAnBA,KAAKU;AACtC"}
1
+ {"version":3,"sources":["../../../src/components/PanelSpecEditor/PanelSpecEditor.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 { ErrorAlert, JSONEditor } from '@perses-dev/components';\nimport { PanelDefinition, QueryDefinition, UnknownSpec } from '@perses-dev/core';\nimport { usePlugin } from '../../runtime';\nimport { PanelPlugin } from '../../model';\nimport { OptionsEditorTabsProps, OptionsEditorTabs } from '../OptionsEditorTabs';\nimport { TimeSeriesQueryEditor } from '../TimeSeriesQueryEditor';\n\nexport interface PanelSpecEditorProps {\n panelDefinition: PanelDefinition;\n onQueriesChange: (queries: QueryDefinition[]) => void;\n onPluginSpecChange: (spec: UnknownSpec) => void;\n onJSONChange: (panelDefinitionStr: string) => void;\n}\n\nexport function PanelSpecEditor(props: PanelSpecEditorProps) {\n const { panelDefinition, onJSONChange, onQueriesChange, onPluginSpecChange } = props;\n const { kind } = panelDefinition.spec.plugin;\n const { data: plugin, isLoading, error } = usePlugin('Panel', kind);\n\n if (error) {\n return <ErrorAlert error={error} />;\n }\n\n // TODO: Proper loading indicator\n if (isLoading) {\n return null;\n }\n\n if (plugin === undefined) {\n throw new Error(`Missing implementation for panel plugin with kind '${kind}'`);\n }\n\n const { panelOptionsEditorComponents, hideQueryEditor } = plugin as PanelPlugin;\n let tabs: OptionsEditorTabsProps['tabs'] = [];\n\n if (!hideQueryEditor) {\n // Since we only support TimeSeriesQuery for now, we will always show a TimeSeriesQueryEditor\n tabs.push({\n label: 'Query',\n content: <TimeSeriesQueryEditor queries={panelDefinition.spec.queries ?? []} onChange={onQueriesChange} />,\n });\n }\n\n if (panelOptionsEditorComponents !== undefined) {\n tabs = tabs.concat(\n panelOptionsEditorComponents.map(({ label, content: OptionsEditorComponent }) => ({\n label,\n content: <OptionsEditorComponent value={panelDefinition.spec.plugin.spec} onChange={onPluginSpecChange} />,\n }))\n );\n }\n\n // always show json editor by default\n tabs.push({\n label: 'JSON',\n content: <JSONEditor maxHeight=\"80vh\" value={panelDefinition} onChange={onJSONChange} />,\n });\n\n return <OptionsEditorTabs key={tabs.length} tabs={tabs} />;\n}\n"],"names":["ErrorAlert","JSONEditor","usePlugin","OptionsEditorTabs","TimeSeriesQueryEditor","PanelSpecEditor","props","panelDefinition","onJSONChange","onQueriesChange","onPluginSpecChange","kind","spec","plugin","data","isLoading","error","undefined","Error","panelOptionsEditorComponents","hideQueryEditor","tabs","push","label","content","queries","onChange","concat","map","OptionsEditorComponent","value","maxHeight","length"],"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,UAAU,EAAEC,UAAU,QAAQ,yBAAyB;AAEhE,SAASC,SAAS,QAAQ,gBAAgB;AAE1C,SAAiCC,iBAAiB,QAAQ,uBAAuB;AACjF,SAASC,qBAAqB,QAAQ,2BAA2B;AASjE,OAAO,SAASC,gBAAgBC,KAA2B;IACzD,MAAM,EAAEC,gBAAe,EAAEC,aAAY,EAAEC,gBAAe,EAAEC,mBAAkB,EAAE,GAAGJ;IAC/E,MAAM,EAAEK,KAAI,EAAE,GAAGJ,gBAAgBK,KAAKC;IACtC,MAAM,EAAEC,MAAMD,OAAM,EAAEE,UAAS,EAAEC,MAAK,EAAE,GAAGd,UAAU,SAASS;IAE9D,IAAIK,OAAO;QACT,qBAAO,KAAChB;YAAWgB,OAAOA;;IAC5B;IAEA,iCAAiC;IACjC,IAAID,WAAW;QACb,OAAO;IACT;IAEA,IAAIF,WAAWI,WAAW;QACxB,MAAM,IAAIC,MAAM,CAAC,mDAAmD,EAAEP,KAAK,CAAC,CAAC;IAC/E;IAEA,MAAM,EAAEQ,6BAA4B,EAAEC,gBAAe,EAAE,GAAGP;IAC1D,IAAIQ,OAAuC,EAAE;IAE7C,IAAI,CAACD,iBAAiB;YAIuBb;QAH3C,6FAA6F;QAC7Fc,KAAKC,KAAK;YACRC,OAAO;YACPC,uBAAS,KAACpB;gBAAsBqB,SAASlB,CAAAA,gCAAAA,gBAAgBK,KAAKa,qBAArBlB,2CAAAA,gCAAgC,EAAE;gBAAEmB,UAAUjB;;QACzF;IACF;IAEA,IAAIU,iCAAiCF,WAAW;QAC9CI,OAAOA,KAAKM,OACVR,6BAA6BS,IAAI,CAAC,EAAEL,MAAK,EAAEC,SAASK,uBAAsB,EAAE,GAAM,CAAA;gBAChFN;gBACAC,uBAAS,KAACK;oBAAuBC,OAAOvB,gBAAgBK,KAAKC,OAAOD;oBAAMc,UAAUhB;;YACtF,CAAA;IAEJ;IAEA,qCAAqC;IACrCW,KAAKC,KAAK;QACRC,OAAO;QACPC,uBAAS,KAACvB;YAAW8B,WAAU;YAAOD,OAAOvB;YAAiBmB,UAAUlB;;IAC1E;IAEA,qBAAO,KAACL;QAAoCkB,MAAMA;OAAnBA,KAAKW;AACtC"}
@@ -1 +1 @@
1
- {"version":3,"file":"PluginEditor.d.ts","sourceRoot":"","sources":["../../../src/components/PluginEditor/PluginEditor.tsx"],"names":[],"mappings":";AAgBA,OAAO,EAAE,iBAAiB,EAAmB,MAAM,qBAAqB,CAAC;AAEzE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,eA4BpD"}
1
+ {"version":3,"file":"PluginEditor.d.ts","sourceRoot":"","sources":["../../../src/components/PluginEditor/PluginEditor.tsx"],"names":[],"mappings":";AAgBA,OAAO,EAAE,iBAAiB,EAAmB,MAAM,qBAAqB,CAAC;AAEzE;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,eA6BpD"}
@@ -24,7 +24,7 @@ import { usePluginEditor } from './plugin-editor-api';
24
24
  * `usePluginEditor` hook that powers this component.
25
25
  */ export function PluginEditor(props) {
26
26
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
27
- const { value , pluginType , pluginKindLabel , onChange: _ , isReadonly , ...others } = props;
27
+ const { value , pluginType , pluginKindLabel , onChange: _ , isReadonly , isExplore , ...others } = props;
28
28
  const { pendingKind , isLoading , error , onKindChange , onSpecChange } = usePluginEditor(props);
29
29
  return /*#__PURE__*/ _jsxs(Box, {
30
30
  ...others,
@@ -48,6 +48,7 @@ import { usePluginEditor } from './plugin-editor-api';
48
48
  onChange: onKindChange
49
49
  }),
50
50
  /*#__PURE__*/ _jsx(PluginSpecEditor, {
51
+ isExplore: isExplore,
51
52
  pluginType: pluginType,
52
53
  pluginKind: value.kind,
53
54
  value: value.spec,