@perses-dev/plugin-system 0.22.0 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/components/OptionsEditorTabs/OptionsEditorTabs.js +4 -47
- package/dist/cjs/components/OptionsEditorTabs/OptionsEditorTabs.test.js +25 -85
- package/dist/cjs/components/PluginSpecEditor.js +38 -4
- package/dist/cjs/components/PluginSpecEditor.test.js +30 -8
- package/dist/cjs/model/panels.js +6 -0
- package/dist/cjs/test/test-plugins/bert/index.js +32 -19
- package/dist/components/OptionsEditorTabs/OptionsEditorTabs.d.ts +3 -24
- package/dist/components/OptionsEditorTabs/OptionsEditorTabs.d.ts.map +1 -1
- package/dist/components/OptionsEditorTabs/OptionsEditorTabs.js +4 -47
- package/dist/components/OptionsEditorTabs/OptionsEditorTabs.js.map +1 -1
- package/dist/components/OptionsEditorTabs/OptionsEditorTabs.test.js +25 -85
- package/dist/components/OptionsEditorTabs/OptionsEditorTabs.test.js.map +1 -1
- package/dist/components/PluginSpecEditor.d.ts.map +1 -1
- package/dist/components/PluginSpecEditor.js +39 -5
- package/dist/components/PluginSpecEditor.js.map +1 -1
- package/dist/components/PluginSpecEditor.test.js +30 -8
- package/dist/components/PluginSpecEditor.test.js.map +1 -1
- package/dist/model/panels.d.ts +14 -2
- package/dist/model/panels.d.ts.map +1 -1
- package/dist/model/panels.js +1 -1
- package/dist/model/panels.js.map +1 -1
- package/dist/model/plugin-base.d.ts +1 -1
- package/dist/model/plugin-base.d.ts.map +1 -1
- package/dist/model/plugin-base.js.map +1 -1
- package/dist/test/test-plugins/bert/index.d.ts.map +1 -1
- package/dist/test/test-plugins/bert/index.js +32 -19
- package/dist/test/test-plugins/bert/index.js.map +1 -1
- package/package.json +3 -3
|
@@ -22,54 +22,11 @@ const _jsxRuntime = require("react/jsx-runtime");
|
|
|
22
22
|
const _material = require("@mui/material");
|
|
23
23
|
const _react = require("react");
|
|
24
24
|
const _tabPanel = require("./TabPanel");
|
|
25
|
-
// Configuration of the order and labeling for tabs across plugins to enforce a
|
|
26
|
-
// consistent UX.
|
|
27
|
-
const TAB_CONFIG = [
|
|
28
|
-
{
|
|
29
|
-
id: 'query',
|
|
30
|
-
label: 'Query'
|
|
31
|
-
},
|
|
32
|
-
{
|
|
33
|
-
id: 'settings',
|
|
34
|
-
label: 'Settings'
|
|
35
|
-
},
|
|
36
|
-
// Custom tabs go between the visual common tabs and the raw JSON editor.
|
|
37
|
-
'other',
|
|
38
|
-
{
|
|
39
|
-
id: 'json',
|
|
40
|
-
label: 'JSON'
|
|
41
|
-
}
|
|
42
|
-
];
|
|
43
25
|
const OptionsEditorTabs = ({ tabs })=>{
|
|
44
26
|
const [activeTab, setActiveTab] = (0, _react.useState)(0);
|
|
45
27
|
const handleChange = (_, newValue)=>{
|
|
46
28
|
setActiveTab(newValue);
|
|
47
29
|
};
|
|
48
|
-
// Normalize the common tabs that are managed via constants in this file
|
|
49
|
-
// and custom tabs that bring their own config into a consistent shape for
|
|
50
|
-
// rendering.
|
|
51
|
-
const normalizedTabs = TAB_CONFIG.reduce((combinedTabs, tabConfig)=>{
|
|
52
|
-
// Custom tabs
|
|
53
|
-
if (tabConfig === 'other') {
|
|
54
|
-
const otherTabs = (tabs === null || tabs === void 0 ? void 0 : tabs.other) || [];
|
|
55
|
-
return [
|
|
56
|
-
...combinedTabs,
|
|
57
|
-
...otherTabs
|
|
58
|
-
];
|
|
59
|
-
}
|
|
60
|
-
// Common tabs
|
|
61
|
-
const commonTab = tabs[tabConfig.id];
|
|
62
|
-
if (commonTab) {
|
|
63
|
-
return [
|
|
64
|
-
...combinedTabs,
|
|
65
|
-
{
|
|
66
|
-
...tabConfig,
|
|
67
|
-
...commonTab
|
|
68
|
-
}
|
|
69
|
-
];
|
|
70
|
-
}
|
|
71
|
-
return combinedTabs;
|
|
72
|
-
}, []);
|
|
73
30
|
return /*#__PURE__*/ (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
74
31
|
children: [
|
|
75
32
|
/*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Box, {
|
|
@@ -81,21 +38,21 @@ const OptionsEditorTabs = ({ tabs })=>{
|
|
|
81
38
|
value: activeTab,
|
|
82
39
|
onChange: handleChange,
|
|
83
40
|
"aria-label": "Panel configuration tabs",
|
|
84
|
-
children:
|
|
41
|
+
children: tabs.map(({ label }, i)=>{
|
|
85
42
|
return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_material.Tab, {
|
|
86
43
|
label: label,
|
|
87
44
|
id: `options-editor-tab-${i}`,
|
|
88
45
|
"aria-controls": `options-editor-tabpanel-${i}`
|
|
89
|
-
},
|
|
46
|
+
}, label);
|
|
90
47
|
})
|
|
91
48
|
})
|
|
92
49
|
}),
|
|
93
|
-
|
|
50
|
+
tabs.map(({ label , content }, i)=>{
|
|
94
51
|
return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_tabPanel.TabPanel, {
|
|
95
52
|
value: activeTab,
|
|
96
53
|
index: i,
|
|
97
54
|
children: content
|
|
98
|
-
},
|
|
55
|
+
}, label);
|
|
99
56
|
})
|
|
100
57
|
]
|
|
101
58
|
});
|
|
@@ -24,46 +24,32 @@ function _interopRequireDefault(obj) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
describe('OptionsEditorTabs', ()=>{
|
|
27
|
+
const mockTabs = [
|
|
28
|
+
{
|
|
29
|
+
label: 'Query',
|
|
30
|
+
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
31
|
+
children: "Edit query configuration"
|
|
32
|
+
})
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
label: 'Settings',
|
|
36
|
+
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
37
|
+
children: "Edit settings configuration"
|
|
38
|
+
})
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
label: 'JSON',
|
|
42
|
+
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
43
|
+
children: "JSON editor"
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
];
|
|
27
47
|
const renderTabs = (otherTabs)=>{
|
|
48
|
+
const tabs = otherTabs !== null && otherTabs !== void 0 ? otherTabs : mockTabs;
|
|
28
49
|
(0, _react.render)(/*#__PURE__*/ (0, _jsxRuntime.jsx)(_optionsEditorTabs.OptionsEditorTabs, {
|
|
29
|
-
tabs:
|
|
30
|
-
query: {
|
|
31
|
-
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
32
|
-
children: "Edit query configuration"
|
|
33
|
-
})
|
|
34
|
-
},
|
|
35
|
-
settings: {
|
|
36
|
-
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
37
|
-
children: "Edit settings configuration"
|
|
38
|
-
})
|
|
39
|
-
},
|
|
40
|
-
json: {
|
|
41
|
-
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
42
|
-
children: "JSON editor"
|
|
43
|
-
})
|
|
44
|
-
},
|
|
45
|
-
other: otherTabs
|
|
46
|
-
}
|
|
50
|
+
tabs: tabs
|
|
47
51
|
}));
|
|
48
52
|
};
|
|
49
|
-
const renderCustomTabs = ()=>{
|
|
50
|
-
renderTabs([
|
|
51
|
-
{
|
|
52
|
-
id: 'tableCols',
|
|
53
|
-
label: 'Table columns',
|
|
54
|
-
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
55
|
-
children: "custom table column"
|
|
56
|
-
})
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
id: 'tableOpts',
|
|
60
|
-
label: 'Table options',
|
|
61
|
-
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
62
|
-
children: "custom table options"
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
]);
|
|
66
|
-
};
|
|
67
53
|
it('renders all specified tabs in a tab list', ()=>{
|
|
68
54
|
renderTabs();
|
|
69
55
|
const tabList = _react.screen.getByRole('tablist');
|
|
@@ -109,59 +95,13 @@ describe('OptionsEditorTabs', ()=>{
|
|
|
109
95
|
const activeTabPanel = _react.screen.getByRole('tabpanel');
|
|
110
96
|
expect(activeTabPanel).toHaveTextContent('settings configuration');
|
|
111
97
|
});
|
|
112
|
-
it('renders
|
|
113
|
-
|
|
98
|
+
it('renders tabs in correct order', ()=>{
|
|
99
|
+
renderTabs();
|
|
114
100
|
const tabList = _react.screen.getByRole('tablist');
|
|
115
101
|
const tabs = (0, _react.getAllByRole)(tabList, 'tab');
|
|
116
|
-
expect(tabs).toHaveLength(
|
|
102
|
+
expect(tabs).toHaveLength(3);
|
|
117
103
|
expect(tabs[0]).toHaveTextContent('Query');
|
|
118
104
|
expect(tabs[1]).toHaveTextContent('Settings');
|
|
119
|
-
expect(tabs[2]).toHaveTextContent('Table column');
|
|
120
|
-
expect(tabs[3]).toHaveTextContent('Table options');
|
|
121
|
-
expect(tabs[4]).toHaveTextContent('JSON');
|
|
122
|
-
});
|
|
123
|
-
it('shows the correct content when selecting a custom tab', ()=>{
|
|
124
|
-
renderCustomTabs();
|
|
125
|
-
const tableColTab = _react.screen.getByRole('tab', {
|
|
126
|
-
name: 'Table columns'
|
|
127
|
-
});
|
|
128
|
-
_userEvent.default.click(tableColTab);
|
|
129
|
-
const activeTab = _react.screen.getByRole('tab', {
|
|
130
|
-
selected: true
|
|
131
|
-
});
|
|
132
|
-
expect(activeTab).toBe(tableColTab);
|
|
133
|
-
const activeTabPanel = _react.screen.getByRole('tabpanel');
|
|
134
|
-
expect(activeTabPanel).toHaveTextContent('custom table column');
|
|
135
|
-
});
|
|
136
|
-
it('only renders common tabs that are specified', ()=>{
|
|
137
|
-
(0, _react.render)(/*#__PURE__*/ (0, _jsxRuntime.jsx)(_optionsEditorTabs.OptionsEditorTabs, {
|
|
138
|
-
tabs: {
|
|
139
|
-
settings: {
|
|
140
|
-
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
141
|
-
children: "settings are alone"
|
|
142
|
-
})
|
|
143
|
-
},
|
|
144
|
-
json: {
|
|
145
|
-
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
146
|
-
children: "JSON is at the end"
|
|
147
|
-
})
|
|
148
|
-
},
|
|
149
|
-
other: [
|
|
150
|
-
{
|
|
151
|
-
id: 'custom',
|
|
152
|
-
label: 'Another tab',
|
|
153
|
-
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
154
|
-
children: "another tab content"
|
|
155
|
-
})
|
|
156
|
-
}
|
|
157
|
-
]
|
|
158
|
-
}
|
|
159
|
-
}));
|
|
160
|
-
const tabList = _react.screen.getByRole('tablist');
|
|
161
|
-
const tabs = (0, _react.getAllByRole)(tabList, 'tab');
|
|
162
|
-
expect(tabs).toHaveLength(3);
|
|
163
|
-
expect(tabs[0]).toHaveTextContent('Settings');
|
|
164
|
-
expect(tabs[1]).toHaveTextContent('Another tab');
|
|
165
105
|
expect(tabs[2]).toHaveTextContent('JSON');
|
|
166
106
|
});
|
|
167
107
|
});
|
|
@@ -21,6 +21,7 @@ Object.defineProperty(exports, "PluginSpecEditor", {
|
|
|
21
21
|
const _jsxRuntime = require("react/jsx-runtime");
|
|
22
22
|
const _components = require("@perses-dev/components");
|
|
23
23
|
const _runtime = require("../runtime");
|
|
24
|
+
const _optionsEditorTabs = require("./OptionsEditorTabs");
|
|
24
25
|
function PluginSpecEditor(props) {
|
|
25
26
|
const { pluginType , pluginKind , ...others } = props;
|
|
26
27
|
const { data: plugin , isLoading , error } = (0, _runtime.usePlugin)(pluginType, pluginKind);
|
|
@@ -34,10 +35,43 @@ function PluginSpecEditor(props) {
|
|
|
34
35
|
return null;
|
|
35
36
|
}
|
|
36
37
|
if (plugin === undefined) {
|
|
37
|
-
throw new Error(`Missing
|
|
38
|
+
throw new Error(`Missing implementation for ${pluginType} plugin with kind '${pluginKind}'`);
|
|
39
|
+
}
|
|
40
|
+
if (pluginType === 'Panel') {
|
|
41
|
+
const { PanelQueryEditorComponent , panelOptionsEditorComponents } = plugin;
|
|
42
|
+
let tabs = [];
|
|
43
|
+
if (PanelQueryEditorComponent !== undefined) {
|
|
44
|
+
tabs.push({
|
|
45
|
+
label: 'Query',
|
|
46
|
+
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)(PanelQueryEditorComponent, {
|
|
47
|
+
...others
|
|
48
|
+
})
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
if (panelOptionsEditorComponents !== undefined) {
|
|
52
|
+
tabs = tabs.concat(panelOptionsEditorComponents.map(({ label , content: OptionsEditorComponent })=>({
|
|
53
|
+
label,
|
|
54
|
+
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)(OptionsEditorComponent, {
|
|
55
|
+
...others
|
|
56
|
+
})
|
|
57
|
+
})));
|
|
58
|
+
}
|
|
59
|
+
// always show json editor by default
|
|
60
|
+
tabs.push({
|
|
61
|
+
label: 'JSON',
|
|
62
|
+
content: /*#__PURE__*/ (0, _jsxRuntime.jsx)(_components.JSONEditor, {
|
|
63
|
+
...others
|
|
64
|
+
})
|
|
65
|
+
});
|
|
66
|
+
return /*#__PURE__*/ (0, _jsxRuntime.jsx)(_optionsEditorTabs.OptionsEditorTabs, {
|
|
67
|
+
tabs: tabs
|
|
68
|
+
});
|
|
38
69
|
}
|
|
39
70
|
const { OptionsEditorComponent } = plugin;
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
71
|
+
if (OptionsEditorComponent !== undefined) {
|
|
72
|
+
return /*#__PURE__*/ (0, _jsxRuntime.jsx)(OptionsEditorComponent, {
|
|
73
|
+
...others
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
return null;
|
|
43
77
|
}
|
|
@@ -30,15 +30,37 @@ describe('PluginSpecEditor', ()=>{
|
|
|
30
30
|
...props
|
|
31
31
|
}));
|
|
32
32
|
};
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
describe('Panel plugin', ()=>{
|
|
34
|
+
it('should show query and json editors', async ()=>{
|
|
35
|
+
renderComponent({
|
|
36
|
+
pluginType: 'Panel',
|
|
37
|
+
pluginKind: 'BertPanel1',
|
|
38
|
+
value: {},
|
|
39
|
+
onChange: jest.fn()
|
|
40
|
+
});
|
|
41
|
+
const queryTab = await _react.screen.findByLabelText('Query');
|
|
42
|
+
expect(queryTab).toBeInTheDocument();
|
|
43
|
+
const editor = await _react.screen.findByLabelText('BertPanel1 editor');
|
|
44
|
+
expect(editor).toBeInTheDocument();
|
|
45
|
+
const jsonEditor = await _react.screen.findByLabelText('JSON');
|
|
46
|
+
expect(jsonEditor).toBeInTheDocument();
|
|
47
|
+
});
|
|
48
|
+
it('should display other options editor components', async ()=>{
|
|
49
|
+
renderComponent({
|
|
50
|
+
pluginType: 'Panel',
|
|
51
|
+
pluginKind: 'BertPanel2',
|
|
52
|
+
value: {},
|
|
53
|
+
onChange: jest.fn()
|
|
54
|
+
});
|
|
55
|
+
const settingsTab = await _react.screen.findByLabelText('Settings');
|
|
56
|
+
expect(settingsTab).toBeInTheDocument();
|
|
57
|
+
const editor = await _react.screen.findByLabelText('BertPanel2 editor');
|
|
58
|
+
expect(editor).toBeInTheDocument();
|
|
59
|
+
const customTab = await _react.screen.findByLabelText('Custom Tab');
|
|
60
|
+
expect(customTab).toBeInTheDocument();
|
|
61
|
+
const jsonEditor = await _react.screen.findByLabelText('JSON');
|
|
62
|
+
expect(jsonEditor).toBeInTheDocument();
|
|
39
63
|
});
|
|
40
|
-
const editor = await _react.screen.findByLabelText('BertPanel1 editor');
|
|
41
|
-
expect(editor).toBeInTheDocument();
|
|
42
64
|
});
|
|
43
65
|
it('propagates value changes', async ()=>{
|
|
44
66
|
const onChange = jest.fn();
|
package/dist/cjs/model/panels.js
CHANGED
|
@@ -27,7 +27,7 @@ _export(exports, {
|
|
|
27
27
|
const _jsxRuntime = require("react/jsx-runtime");
|
|
28
28
|
const BertPanel1 = {
|
|
29
29
|
PanelComponent: ()=>null,
|
|
30
|
-
|
|
30
|
+
PanelQueryEditorComponent: function BertPanel1Editor({ value , onChange }) {
|
|
31
31
|
return /*#__PURE__*/ (0, _jsxRuntime.jsxs)("div", {
|
|
32
32
|
children: [
|
|
33
33
|
/*#__PURE__*/ (0, _jsxRuntime.jsx)("label", {
|
|
@@ -52,25 +52,38 @@ const BertPanel1 = {
|
|
|
52
52
|
};
|
|
53
53
|
const BertPanel2 = {
|
|
54
54
|
PanelComponent: ()=>null,
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
children:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
55
|
+
panelOptionsEditorComponents: [
|
|
56
|
+
{
|
|
57
|
+
label: 'Settings',
|
|
58
|
+
content: function BertPanel2Editor({ value , onChange }) {
|
|
59
|
+
return /*#__PURE__*/ (0, _jsxRuntime.jsxs)("div", {
|
|
60
|
+
children: [
|
|
61
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsx)("label", {
|
|
62
|
+
htmlFor: "editor-input",
|
|
63
|
+
children: "BertPanel2 editor"
|
|
64
|
+
}),
|
|
65
|
+
/*#__PURE__*/ (0, _jsxRuntime.jsx)("input", {
|
|
66
|
+
type: "text",
|
|
67
|
+
id: "editor-input",
|
|
68
|
+
value: value.option2,
|
|
69
|
+
onChange: (e)=>onChange({
|
|
70
|
+
...value,
|
|
71
|
+
option2: e.target.value
|
|
72
|
+
})
|
|
69
73
|
})
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
+
]
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
label: 'Custom Tab',
|
|
80
|
+
content: function Editor() {
|
|
81
|
+
return /*#__PURE__*/ (0, _jsxRuntime.jsx)("div", {
|
|
82
|
+
children: "custom content"
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
],
|
|
74
87
|
createInitialOptions: ()=>({
|
|
75
88
|
option2: ''
|
|
76
89
|
})
|
|
@@ -1,34 +1,13 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
export declare type OptionsEditorTab = {
|
|
3
|
+
label: string;
|
|
4
4
|
/**
|
|
5
5
|
* Content rendered when the tab is active.
|
|
6
6
|
*/
|
|
7
7
|
content: React.ReactNode;
|
|
8
|
-
}
|
|
9
|
-
interface OtherTabConfig extends BaseTabConfig {
|
|
10
|
-
id: string;
|
|
11
|
-
label: TabProps['label'];
|
|
12
|
-
}
|
|
13
|
-
declare type CommonTabId = 'query' | 'settings' | 'json';
|
|
14
|
-
/**
|
|
15
|
-
* Common tabs that are frequently used in the options editor across multiple
|
|
16
|
-
* plugins. The label and display order of these tabs is not configurable to
|
|
17
|
-
* avoid user experience inconsistencies across plugins.
|
|
18
|
-
*/
|
|
19
|
-
declare type CommonTabs = {
|
|
20
|
-
[property in CommonTabId]?: BaseTabConfig;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Custom tabs specified for a given plugin. They are displayed after common
|
|
24
|
-
* tabs.
|
|
25
|
-
*/
|
|
26
|
-
declare type OtherTabs = {
|
|
27
|
-
other?: OtherTabConfig[];
|
|
28
8
|
};
|
|
29
9
|
export declare type OptionsEditorTabsProps = {
|
|
30
|
-
tabs:
|
|
10
|
+
tabs: OptionsEditorTab[];
|
|
31
11
|
};
|
|
32
12
|
export declare const OptionsEditorTabs: ({ tabs }: OptionsEditorTabsProps) => JSX.Element;
|
|
33
|
-
export {};
|
|
34
13
|
//# sourceMappingURL=OptionsEditorTabs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"OptionsEditorTabs.d.ts","sourceRoot":"","sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"OptionsEditorTabs.d.ts","sourceRoot":"","sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.tsx"],"names":[],"mappings":";AAiBA,oBAAY,gBAAgB,GAAG;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;CAC1B,CAAC;AAEF,oBAAY,sBAAsB,GAAG;IACnC,IAAI,EAAE,gBAAgB,EAAE,CAAC;CAC1B,CAAC;AAEF,eAAO,MAAM,iBAAiB,aAAc,sBAAsB,gBAgCjE,CAAC"}
|
|
@@ -14,54 +14,11 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
14
14
|
import { Tab, Tabs, Box } from '@mui/material';
|
|
15
15
|
import { useState } from 'react';
|
|
16
16
|
import { TabPanel } from './TabPanel';
|
|
17
|
-
// Configuration of the order and labeling for tabs across plugins to enforce a
|
|
18
|
-
// consistent UX.
|
|
19
|
-
const TAB_CONFIG = [
|
|
20
|
-
{
|
|
21
|
-
id: 'query',
|
|
22
|
-
label: 'Query'
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
id: 'settings',
|
|
26
|
-
label: 'Settings'
|
|
27
|
-
},
|
|
28
|
-
// Custom tabs go between the visual common tabs and the raw JSON editor.
|
|
29
|
-
'other',
|
|
30
|
-
{
|
|
31
|
-
id: 'json',
|
|
32
|
-
label: 'JSON'
|
|
33
|
-
}
|
|
34
|
-
];
|
|
35
17
|
export const OptionsEditorTabs = ({ tabs })=>{
|
|
36
18
|
const [activeTab, setActiveTab] = useState(0);
|
|
37
19
|
const handleChange = (_, newValue)=>{
|
|
38
20
|
setActiveTab(newValue);
|
|
39
21
|
};
|
|
40
|
-
// Normalize the common tabs that are managed via constants in this file
|
|
41
|
-
// and custom tabs that bring their own config into a consistent shape for
|
|
42
|
-
// rendering.
|
|
43
|
-
const normalizedTabs = TAB_CONFIG.reduce((combinedTabs, tabConfig)=>{
|
|
44
|
-
// Custom tabs
|
|
45
|
-
if (tabConfig === 'other') {
|
|
46
|
-
const otherTabs = (tabs === null || tabs === void 0 ? void 0 : tabs.other) || [];
|
|
47
|
-
return [
|
|
48
|
-
...combinedTabs,
|
|
49
|
-
...otherTabs
|
|
50
|
-
];
|
|
51
|
-
}
|
|
52
|
-
// Common tabs
|
|
53
|
-
const commonTab = tabs[tabConfig.id];
|
|
54
|
-
if (commonTab) {
|
|
55
|
-
return [
|
|
56
|
-
...combinedTabs,
|
|
57
|
-
{
|
|
58
|
-
...tabConfig,
|
|
59
|
-
...commonTab
|
|
60
|
-
}
|
|
61
|
-
];
|
|
62
|
-
}
|
|
63
|
-
return combinedTabs;
|
|
64
|
-
}, []);
|
|
65
22
|
return /*#__PURE__*/ _jsxs(_Fragment, {
|
|
66
23
|
children: [
|
|
67
24
|
/*#__PURE__*/ _jsx(Box, {
|
|
@@ -73,21 +30,21 @@ export const OptionsEditorTabs = ({ tabs })=>{
|
|
|
73
30
|
value: activeTab,
|
|
74
31
|
onChange: handleChange,
|
|
75
32
|
"aria-label": "Panel configuration tabs",
|
|
76
|
-
children:
|
|
33
|
+
children: tabs.map(({ label }, i)=>{
|
|
77
34
|
return /*#__PURE__*/ _jsx(Tab, {
|
|
78
35
|
label: label,
|
|
79
36
|
id: `options-editor-tab-${i}`,
|
|
80
37
|
"aria-controls": `options-editor-tabpanel-${i}`
|
|
81
|
-
},
|
|
38
|
+
}, label);
|
|
82
39
|
})
|
|
83
40
|
})
|
|
84
41
|
}),
|
|
85
|
-
|
|
42
|
+
tabs.map(({ label , content }, i)=>{
|
|
86
43
|
return /*#__PURE__*/ _jsx(TabPanel, {
|
|
87
44
|
value: activeTab,
|
|
88
45
|
index: i,
|
|
89
46
|
children: content
|
|
90
|
-
},
|
|
47
|
+
}, label);
|
|
91
48
|
})
|
|
92
49
|
]
|
|
93
50
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.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 { Tab,
|
|
1
|
+
{"version":3,"sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.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 { Tab, Tabs, TabsProps, Box } from '@mui/material';\nimport { useState } from 'react';\nimport { TabPanel } from './TabPanel';\n\nexport type OptionsEditorTab = {\n label: string;\n /**\n * Content rendered when the tab is active.\n */\n content: React.ReactNode;\n};\n\nexport type OptionsEditorTabsProps = {\n tabs: OptionsEditorTab[];\n};\n\nexport const OptionsEditorTabs = ({ tabs }: OptionsEditorTabsProps) => {\n const [activeTab, setActiveTab] = useState(0);\n\n const handleChange: TabsProps['onChange'] = (_, newValue) => {\n setActiveTab(newValue);\n };\n\n return (\n <>\n <Box sx={{ borderBottom: 1, borderColor: (theme) => theme.palette.divider }}>\n <Tabs value={activeTab} onChange={handleChange} aria-label=\"Panel configuration tabs\">\n {tabs.map(({ label }, i) => {\n return (\n <Tab\n key={label}\n label={label}\n id={`options-editor-tab-${i}`}\n aria-controls={`options-editor-tabpanel-${i}`}\n />\n );\n })}\n </Tabs>\n </Box>\n {tabs.map(({ label, content }, i) => {\n return (\n <TabPanel key={label} value={activeTab} index={i}>\n {content}\n </TabPanel>\n );\n })}\n </>\n );\n};\n"],"names":["Tab","Tabs","Box","useState","TabPanel","OptionsEditorTabs","tabs","activeTab","setActiveTab","handleChange","_","newValue","sx","borderBottom","borderColor","theme","palette","divider","value","onChange","aria-label","map","label","i","id","aria-controls","content","index"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,GAAG,EAAEC,IAAI,EAAaC,GAAG,QAAQ,eAAe,CAAC;AAC1D,SAASC,QAAQ,QAAQ,OAAO,CAAC;AACjC,SAASC,QAAQ,QAAQ,YAAY,CAAC;AActC,OAAO,MAAMC,iBAAiB,GAAG,CAAC,EAAEC,IAAI,CAAA,EAA0B,GAAK;IACrE,MAAM,CAACC,SAAS,EAAEC,YAAY,CAAC,GAAGL,QAAQ,CAAC,CAAC,CAAC,AAAC;IAE9C,MAAMM,YAAY,GAA0B,CAACC,CAAC,EAAEC,QAAQ,GAAK;QAC3DH,YAAY,CAACG,QAAQ,CAAC,CAAC;IACzB,CAAC,AAAC;IAEF,qBACE;;0BACE,KAACT,GAAG;gBAACU,EAAE,EAAE;oBAAEC,YAAY,EAAE,CAAC;oBAAEC,WAAW,EAAE,CAACC,KAAK,GAAKA,KAAK,CAACC,OAAO,CAACC,OAAO;iBAAE;0BACzE,cAAA,KAAChB,IAAI;oBAACiB,KAAK,EAAEX,SAAS;oBAAEY,QAAQ,EAAEV,YAAY;oBAAEW,YAAU,EAAC,0BAA0B;8BAClFd,IAAI,CAACe,GAAG,CAAC,CAAC,EAAEC,KAAK,CAAA,EAAE,EAAEC,CAAC,GAAK;wBAC1B,qBACE,KAACvB,GAAG;4BAEFsB,KAAK,EAAEA,KAAK;4BACZE,EAAE,EAAE,CAAC,mBAAmB,EAAED,CAAC,CAAC,CAAC;4BAC7BE,eAAa,EAAE,CAAC,wBAAwB,EAAEF,CAAC,CAAC,CAAC;2BAHxCD,KAAK,CAIV,CACF;oBACJ,CAAC,CAAC;kBACG;cACH;YACLhB,IAAI,CAACe,GAAG,CAAC,CAAC,EAAEC,KAAK,CAAA,EAAEI,OAAO,CAAA,EAAE,EAAEH,CAAC,GAAK;gBACnC,qBACE,KAACnB,QAAQ;oBAAac,KAAK,EAAEX,SAAS;oBAAEoB,KAAK,EAAEJ,CAAC;8BAC7CG,OAAO;mBADKJ,KAAK,CAET,CACX;YACJ,CAAC,CAAC;;MACD,CACH;AACJ,CAAC,CAAC"}
|
|
@@ -15,46 +15,32 @@ import { screen, render, getAllByRole } from '@testing-library/react';
|
|
|
15
15
|
import userEvent from '@testing-library/user-event';
|
|
16
16
|
import { OptionsEditorTabs } from './OptionsEditorTabs';
|
|
17
17
|
describe('OptionsEditorTabs', ()=>{
|
|
18
|
+
const mockTabs = [
|
|
19
|
+
{
|
|
20
|
+
label: 'Query',
|
|
21
|
+
content: /*#__PURE__*/ _jsx("div", {
|
|
22
|
+
children: "Edit query configuration"
|
|
23
|
+
})
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
label: 'Settings',
|
|
27
|
+
content: /*#__PURE__*/ _jsx("div", {
|
|
28
|
+
children: "Edit settings configuration"
|
|
29
|
+
})
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
label: 'JSON',
|
|
33
|
+
content: /*#__PURE__*/ _jsx("div", {
|
|
34
|
+
children: "JSON editor"
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
];
|
|
18
38
|
const renderTabs = (otherTabs)=>{
|
|
39
|
+
const tabs = otherTabs !== null && otherTabs !== void 0 ? otherTabs : mockTabs;
|
|
19
40
|
render(/*#__PURE__*/ _jsx(OptionsEditorTabs, {
|
|
20
|
-
tabs:
|
|
21
|
-
query: {
|
|
22
|
-
content: /*#__PURE__*/ _jsx("div", {
|
|
23
|
-
children: "Edit query configuration"
|
|
24
|
-
})
|
|
25
|
-
},
|
|
26
|
-
settings: {
|
|
27
|
-
content: /*#__PURE__*/ _jsx("div", {
|
|
28
|
-
children: "Edit settings configuration"
|
|
29
|
-
})
|
|
30
|
-
},
|
|
31
|
-
json: {
|
|
32
|
-
content: /*#__PURE__*/ _jsx("div", {
|
|
33
|
-
children: "JSON editor"
|
|
34
|
-
})
|
|
35
|
-
},
|
|
36
|
-
other: otherTabs
|
|
37
|
-
}
|
|
41
|
+
tabs: tabs
|
|
38
42
|
}));
|
|
39
43
|
};
|
|
40
|
-
const renderCustomTabs = ()=>{
|
|
41
|
-
renderTabs([
|
|
42
|
-
{
|
|
43
|
-
id: 'tableCols',
|
|
44
|
-
label: 'Table columns',
|
|
45
|
-
content: /*#__PURE__*/ _jsx("div", {
|
|
46
|
-
children: "custom table column"
|
|
47
|
-
})
|
|
48
|
-
},
|
|
49
|
-
{
|
|
50
|
-
id: 'tableOpts',
|
|
51
|
-
label: 'Table options',
|
|
52
|
-
content: /*#__PURE__*/ _jsx("div", {
|
|
53
|
-
children: "custom table options"
|
|
54
|
-
})
|
|
55
|
-
}
|
|
56
|
-
]);
|
|
57
|
-
};
|
|
58
44
|
it('renders all specified tabs in a tab list', ()=>{
|
|
59
45
|
renderTabs();
|
|
60
46
|
const tabList = screen.getByRole('tablist');
|
|
@@ -100,59 +86,13 @@ describe('OptionsEditorTabs', ()=>{
|
|
|
100
86
|
const activeTabPanel = screen.getByRole('tabpanel');
|
|
101
87
|
expect(activeTabPanel).toHaveTextContent('settings configuration');
|
|
102
88
|
});
|
|
103
|
-
it('renders
|
|
104
|
-
|
|
89
|
+
it('renders tabs in correct order', ()=>{
|
|
90
|
+
renderTabs();
|
|
105
91
|
const tabList = screen.getByRole('tablist');
|
|
106
92
|
const tabs = getAllByRole(tabList, 'tab');
|
|
107
|
-
expect(tabs).toHaveLength(
|
|
93
|
+
expect(tabs).toHaveLength(3);
|
|
108
94
|
expect(tabs[0]).toHaveTextContent('Query');
|
|
109
95
|
expect(tabs[1]).toHaveTextContent('Settings');
|
|
110
|
-
expect(tabs[2]).toHaveTextContent('Table column');
|
|
111
|
-
expect(tabs[3]).toHaveTextContent('Table options');
|
|
112
|
-
expect(tabs[4]).toHaveTextContent('JSON');
|
|
113
|
-
});
|
|
114
|
-
it('shows the correct content when selecting a custom tab', ()=>{
|
|
115
|
-
renderCustomTabs();
|
|
116
|
-
const tableColTab = screen.getByRole('tab', {
|
|
117
|
-
name: 'Table columns'
|
|
118
|
-
});
|
|
119
|
-
userEvent.click(tableColTab);
|
|
120
|
-
const activeTab = screen.getByRole('tab', {
|
|
121
|
-
selected: true
|
|
122
|
-
});
|
|
123
|
-
expect(activeTab).toBe(tableColTab);
|
|
124
|
-
const activeTabPanel = screen.getByRole('tabpanel');
|
|
125
|
-
expect(activeTabPanel).toHaveTextContent('custom table column');
|
|
126
|
-
});
|
|
127
|
-
it('only renders common tabs that are specified', ()=>{
|
|
128
|
-
render(/*#__PURE__*/ _jsx(OptionsEditorTabs, {
|
|
129
|
-
tabs: {
|
|
130
|
-
settings: {
|
|
131
|
-
content: /*#__PURE__*/ _jsx("div", {
|
|
132
|
-
children: "settings are alone"
|
|
133
|
-
})
|
|
134
|
-
},
|
|
135
|
-
json: {
|
|
136
|
-
content: /*#__PURE__*/ _jsx("div", {
|
|
137
|
-
children: "JSON is at the end"
|
|
138
|
-
})
|
|
139
|
-
},
|
|
140
|
-
other: [
|
|
141
|
-
{
|
|
142
|
-
id: 'custom',
|
|
143
|
-
label: 'Another tab',
|
|
144
|
-
content: /*#__PURE__*/ _jsx("div", {
|
|
145
|
-
children: "another tab content"
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
]
|
|
149
|
-
}
|
|
150
|
-
}));
|
|
151
|
-
const tabList = screen.getByRole('tablist');
|
|
152
|
-
const tabs = getAllByRole(tabList, 'tab');
|
|
153
|
-
expect(tabs).toHaveLength(3);
|
|
154
|
-
expect(tabs[0]).toHaveTextContent('Settings');
|
|
155
|
-
expect(tabs[1]).toHaveTextContent('Another tab');
|
|
156
96
|
expect(tabs[2]).toHaveTextContent('JSON');
|
|
157
97
|
});
|
|
158
98
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.test.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 { screen, render, getAllByRole } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\n\nimport { OptionsEditorTabs, OptionsEditorTabsProps } from './OptionsEditorTabs';\n\ndescribe('OptionsEditorTabs', () => {\n const renderTabs = (otherTabs?: OptionsEditorTabsProps['tabs']['other']) => {\n render(\n <OptionsEditorTabs\n tabs={{\n query: {\n content: <div>Edit query configuration</div>,\n },\n settings: {\n content: <div>Edit settings configuration</div>,\n },\n json: {\n content: <div>JSON editor</div>,\n },\n other: otherTabs,\n }}\n />\n );\n };\n\n const renderCustomTabs = () => {\n renderTabs([\n {\n id: 'tableCols',\n label: 'Table columns',\n content: <div>custom table column</div>,\n },\n {\n id: 'tableOpts',\n label: 'Table options',\n content: <div>custom table options</div>,\n },\n ]);\n };\n\n it('renders all specified tabs in a tab list', () => {\n renderTabs();\n\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(3);\n expect(tabs[0]).toHaveTextContent('Query');\n expect(tabs[1]).toHaveTextContent('Settings');\n expect(tabs[2]).toHaveTextContent('JSON');\n });\n\n it('defaults to selecting the first tab', () => {\n renderTabs();\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toHaveTextContent('Query');\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('query configuration');\n });\n\n it('switches selected tab on click', () => {\n renderTabs();\n const jsonTab = screen.getByRole('tab', { name: 'JSON' });\n userEvent.click(jsonTab);\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(jsonTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('JSON editor');\n });\n\n it('switches selected tab on keyboard interactions', () => {\n renderTabs();\n const vizTab = screen.getByRole('tab', { name: 'Settings' });\n userEvent.tab();\n userEvent.keyboard('{arrowright}{space}');\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(vizTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('settings configuration');\n });\n\n it('renders custom tabs between visual tabs and json editor', () => {\n renderCustomTabs();\n\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(5);\n expect(tabs[0]).toHaveTextContent('Query');\n expect(tabs[1]).toHaveTextContent('Settings');\n expect(tabs[2]).toHaveTextContent('Table column');\n expect(tabs[3]).toHaveTextContent('Table options');\n expect(tabs[4]).toHaveTextContent('JSON');\n });\n\n it('shows the correct content when selecting a custom tab', () => {\n renderCustomTabs();\n\n const tableColTab = screen.getByRole('tab', { name: 'Table columns' });\n userEvent.click(tableColTab);\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(tableColTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('custom table column');\n });\n\n it('only renders common tabs that are specified', () => {\n render(\n <OptionsEditorTabs\n tabs={{\n settings: {\n content: <div>settings are alone</div>,\n },\n json: {\n content: <div>JSON is at the end</div>,\n },\n other: [\n {\n id: 'custom',\n label: 'Another tab',\n content: <div>another tab content</div>,\n },\n ],\n }}\n />\n );\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(3);\n expect(tabs[0]).toHaveTextContent('Settings');\n expect(tabs[1]).toHaveTextContent('Another tab');\n expect(tabs[2]).toHaveTextContent('JSON');\n });\n});\n"],"names":["screen","render","getAllByRole","userEvent","OptionsEditorTabs","describe","renderTabs","otherTabs","tabs","query","content","div","settings","json","other","renderCustomTabs","id","label","it","tabList","getByRole","expect","toHaveLength","toHaveTextContent","activeTab","selected","activeTabPanel","jsonTab","name","click","toBe","vizTab","tab","keyboard","tableColTab"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/components/OptionsEditorTabs/OptionsEditorTabs.test.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 { screen, render, getAllByRole } from '@testing-library/react';\nimport userEvent from '@testing-library/user-event';\n\nimport { OptionsEditorTabs, OptionsEditorTabsProps } from './OptionsEditorTabs';\n\ndescribe('OptionsEditorTabs', () => {\n const mockTabs: OptionsEditorTabsProps['tabs'] = [\n {\n label: 'Query',\n content: <div>Edit query configuration</div>,\n },\n {\n label: 'Settings',\n content: <div>Edit settings configuration</div>,\n },\n {\n label: 'JSON',\n content: <div>JSON editor</div>,\n },\n ];\n const renderTabs = (otherTabs?: OptionsEditorTabsProps['tabs']) => {\n const tabs = otherTabs ?? mockTabs;\n render(<OptionsEditorTabs tabs={tabs} />);\n };\n\n it('renders all specified tabs in a tab list', () => {\n renderTabs();\n\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(3);\n expect(tabs[0]).toHaveTextContent('Query');\n expect(tabs[1]).toHaveTextContent('Settings');\n expect(tabs[2]).toHaveTextContent('JSON');\n });\n\n it('defaults to selecting the first tab', () => {\n renderTabs();\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toHaveTextContent('Query');\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('query configuration');\n });\n\n it('switches selected tab on click', () => {\n renderTabs();\n const jsonTab = screen.getByRole('tab', { name: 'JSON' });\n userEvent.click(jsonTab);\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(jsonTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('JSON editor');\n });\n\n it('switches selected tab on keyboard interactions', () => {\n renderTabs();\n const vizTab = screen.getByRole('tab', { name: 'Settings' });\n userEvent.tab();\n userEvent.keyboard('{arrowright}{space}');\n\n const activeTab = screen.getByRole('tab', {\n selected: true,\n });\n expect(activeTab).toBe(vizTab);\n\n const activeTabPanel = screen.getByRole('tabpanel');\n expect(activeTabPanel).toHaveTextContent('settings configuration');\n });\n\n it('renders tabs in correct order', () => {\n renderTabs();\n\n const tabList = screen.getByRole('tablist');\n const tabs = getAllByRole(tabList, 'tab');\n expect(tabs).toHaveLength(3);\n expect(tabs[0]).toHaveTextContent('Query');\n expect(tabs[1]).toHaveTextContent('Settings');\n expect(tabs[2]).toHaveTextContent('JSON');\n });\n});\n"],"names":["screen","render","getAllByRole","userEvent","OptionsEditorTabs","describe","mockTabs","label","content","div","renderTabs","otherTabs","tabs","it","tabList","getByRole","expect","toHaveLength","toHaveTextContent","activeTab","selected","activeTabPanel","jsonTab","name","click","toBe","vizTab","tab","keyboard"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PluginSpecEditor.d.ts","sourceRoot":"","sources":["../../src/components/PluginSpecEditor.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"PluginSpecEditor.d.ts","sourceRoot":"","sources":["../../src/components/PluginSpecEditor.tsx"],"names":[],"mappings":";AAcA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAe,UAAU,EAAE,MAAM,UAAU,CAAC;AAIvE,MAAM,WAAW,qBAAsB,SAAQ,kBAAkB,CAAC,WAAW,CAAC;IAC5E,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,sBA8C5D"}
|
|
@@ -11,8 +11,9 @@
|
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
13
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
-
import { ErrorAlert } from '@perses-dev/components';
|
|
14
|
+
import { ErrorAlert, JSONEditor } from '@perses-dev/components';
|
|
15
15
|
import { usePlugin } from '../runtime';
|
|
16
|
+
import { OptionsEditorTabs } from './OptionsEditorTabs';
|
|
16
17
|
export function PluginSpecEditor(props) {
|
|
17
18
|
const { pluginType , pluginKind , ...others } = props;
|
|
18
19
|
const { data: plugin , isLoading , error } = usePlugin(pluginType, pluginKind);
|
|
@@ -26,12 +27,45 @@ export function PluginSpecEditor(props) {
|
|
|
26
27
|
return null;
|
|
27
28
|
}
|
|
28
29
|
if (plugin === undefined) {
|
|
29
|
-
throw new Error(`Missing
|
|
30
|
+
throw new Error(`Missing implementation for ${pluginType} plugin with kind '${pluginKind}'`);
|
|
31
|
+
}
|
|
32
|
+
if (pluginType === 'Panel') {
|
|
33
|
+
const { PanelQueryEditorComponent , panelOptionsEditorComponents } = plugin;
|
|
34
|
+
let tabs = [];
|
|
35
|
+
if (PanelQueryEditorComponent !== undefined) {
|
|
36
|
+
tabs.push({
|
|
37
|
+
label: 'Query',
|
|
38
|
+
content: /*#__PURE__*/ _jsx(PanelQueryEditorComponent, {
|
|
39
|
+
...others
|
|
40
|
+
})
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
if (panelOptionsEditorComponents !== undefined) {
|
|
44
|
+
tabs = tabs.concat(panelOptionsEditorComponents.map(({ label , content: OptionsEditorComponent })=>({
|
|
45
|
+
label,
|
|
46
|
+
content: /*#__PURE__*/ _jsx(OptionsEditorComponent, {
|
|
47
|
+
...others
|
|
48
|
+
})
|
|
49
|
+
})));
|
|
50
|
+
}
|
|
51
|
+
// always show json editor by default
|
|
52
|
+
tabs.push({
|
|
53
|
+
label: 'JSON',
|
|
54
|
+
content: /*#__PURE__*/ _jsx(JSONEditor, {
|
|
55
|
+
...others
|
|
56
|
+
})
|
|
57
|
+
});
|
|
58
|
+
return /*#__PURE__*/ _jsx(OptionsEditorTabs, {
|
|
59
|
+
tabs: tabs
|
|
60
|
+
});
|
|
30
61
|
}
|
|
31
62
|
const { OptionsEditorComponent } = plugin;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
63
|
+
if (OptionsEditorComponent !== undefined) {
|
|
64
|
+
return /*#__PURE__*/ _jsx(OptionsEditorComponent, {
|
|
65
|
+
...others
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
35
69
|
}
|
|
36
70
|
|
|
37
71
|
//# sourceMappingURL=PluginSpecEditor.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/PluginSpecEditor.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 } from '@perses-dev/components';\nimport { UnknownSpec } from '@perses-dev/core';\nimport { OptionsEditorProps, PluginType } from '../model';\nimport { usePlugin } from '../runtime';\n\nexport interface PluginSpecEditorProps extends OptionsEditorProps<UnknownSpec> {\n pluginType: PluginType;\n pluginKind: string;\n}\n\nexport function PluginSpecEditor(props: PluginSpecEditorProps) {\n const { pluginType, pluginKind, ...others } = props;\n const { data: plugin, isLoading, error } = usePlugin(pluginType, pluginKind);\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
|
|
1
|
+
{"version":3,"sources":["../../src/components/PluginSpecEditor.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 { UnknownSpec } from '@perses-dev/core';\nimport { OptionsEditorProps, PanelPlugin, PluginType } from '../model';\nimport { usePlugin } from '../runtime';\nimport { OptionsEditorTabsProps, OptionsEditorTabs } from './OptionsEditorTabs';\n\nexport interface PluginSpecEditorProps extends OptionsEditorProps<UnknownSpec> {\n pluginType: PluginType;\n pluginKind: string;\n}\n\nexport function PluginSpecEditor(props: PluginSpecEditorProps) {\n const { pluginType, pluginKind, ...others } = props;\n const { data: plugin, isLoading, error } = usePlugin(pluginType, pluginKind);\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 ${pluginType} plugin with kind '${pluginKind}'`);\n }\n\n if (pluginType === 'Panel') {\n const { PanelQueryEditorComponent, panelOptionsEditorComponents } = plugin as PanelPlugin;\n let tabs: OptionsEditorTabsProps['tabs'] = [];\n if (PanelQueryEditorComponent !== undefined) {\n tabs.push({ label: 'Query', content: <PanelQueryEditorComponent {...others} /> });\n }\n\n if (panelOptionsEditorComponents !== undefined) {\n tabs = tabs.concat(\n panelOptionsEditorComponents.map(({ label, content: OptionsEditorComponent }) => ({\n label,\n content: <OptionsEditorComponent {...others} />,\n }))\n );\n }\n\n // always show json editor by default\n tabs.push({ label: 'JSON', content: <JSONEditor {...others} /> });\n\n return <OptionsEditorTabs tabs={tabs} />;\n }\n\n const { OptionsEditorComponent } = plugin;\n\n if (OptionsEditorComponent !== undefined) {\n return <OptionsEditorComponent {...others} />;\n }\n\n return null;\n}\n"],"names":["ErrorAlert","JSONEditor","usePlugin","OptionsEditorTabs","PluginSpecEditor","props","pluginType","pluginKind","others","data","plugin","isLoading","error","undefined","Error","PanelQueryEditorComponent","panelOptionsEditorComponents","tabs","push","label","content","concat","map","OptionsEditorComponent"],"mappings":"AAAA,oCAAoC;AACpC,kEAAkE;AAClE,mEAAmE;AACnE,0CAA0C;AAC1C,EAAE;AACF,6CAA6C;AAC7C,EAAE;AACF,sEAAsE;AACtE,oEAAoE;AACpE,2EAA2E;AAC3E,sEAAsE;AACtE,iCAAiC;AAEjC;AAAA,SAASA,UAAU,EAAEC,UAAU,QAAQ,wBAAwB,CAAC;AAGhE,SAASC,SAAS,QAAQ,YAAY,CAAC;AACvC,SAAiCC,iBAAiB,QAAQ,qBAAqB,CAAC;AAOhF,OAAO,SAASC,gBAAgB,CAACC,KAA4B,EAAE;IAC7D,MAAM,EAAEC,UAAU,CAAA,EAAEC,UAAU,CAAA,EAAE,GAAGC,MAAM,EAAE,GAAGH,KAAK,AAAC;IACpD,MAAM,EAAEI,IAAI,EAAEC,MAAM,CAAA,EAAEC,SAAS,CAAA,EAAEC,KAAK,CAAA,EAAE,GAAGV,SAAS,CAACI,UAAU,EAAEC,UAAU,CAAC,AAAC;IAE7E,IAAIK,KAAK,EAAE;QACT,qBAAO,KAACZ,UAAU;YAACY,KAAK,EAAEA,KAAK;UAAI,CAAC;IACtC,CAAC;IAED,iCAAiC;IACjC,IAAID,SAAS,EAAE;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAID,MAAM,KAAKG,SAAS,EAAE;QACxB,MAAM,IAAIC,KAAK,CAAC,CAAC,2BAA2B,EAAER,UAAU,CAAC,mBAAmB,EAAEC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,CAAC;IAED,IAAID,UAAU,KAAK,OAAO,EAAE;QAC1B,MAAM,EAAES,yBAAyB,CAAA,EAAEC,4BAA4B,CAAA,EAAE,GAAGN,MAAM,AAAe,AAAC;QAC1F,IAAIO,IAAI,GAAmC,EAAE,AAAC;QAC9C,IAAIF,yBAAyB,KAAKF,SAAS,EAAE;YAC3CI,IAAI,CAACC,IAAI,CAAC;gBAAEC,KAAK,EAAE,OAAO;gBAAEC,OAAO,gBAAE,KAACL,yBAAyB;oBAAE,GAAGP,MAAM;kBAAI;aAAE,CAAC,CAAC;QACpF,CAAC;QAED,IAAIQ,4BAA4B,KAAKH,SAAS,EAAE;YAC9CI,IAAI,GAAGA,IAAI,CAACI,MAAM,CAChBL,4BAA4B,CAACM,GAAG,CAAC,CAAC,EAAEH,KAAK,CAAA,EAAEC,OAAO,EAAEG,sBAAsB,CAAA,EAAE,GAAM,CAAA;oBAChFJ,KAAK;oBACLC,OAAO,gBAAE,KAACG,sBAAsB;wBAAE,GAAGf,MAAM;sBAAI;iBAChD,CAAA,AAAC,CAAC,CACJ,CAAC;QACJ,CAAC;QAED,qCAAqC;QACrCS,IAAI,CAACC,IAAI,CAAC;YAAEC,KAAK,EAAE,MAAM;YAAEC,OAAO,gBAAE,KAACnB,UAAU;gBAAE,GAAGO,MAAM;cAAI;SAAE,CAAC,CAAC;QAElE,qBAAO,KAACL,iBAAiB;YAACc,IAAI,EAAEA,IAAI;UAAI,CAAC;IAC3C,CAAC;IAED,MAAM,EAAEM,sBAAsB,CAAA,EAAE,GAAGb,MAAM,AAAC;IAE1C,IAAIa,sBAAsB,KAAKV,SAAS,EAAE;QACxC,qBAAO,KAACU,sBAAsB;YAAE,GAAGf,MAAM;UAAI,CAAC;IAChD,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -21,15 +21,37 @@ describe('PluginSpecEditor', ()=>{
|
|
|
21
21
|
...props
|
|
22
22
|
}));
|
|
23
23
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
describe('Panel plugin', ()=>{
|
|
25
|
+
it('should show query and json editors', async ()=>{
|
|
26
|
+
renderComponent({
|
|
27
|
+
pluginType: 'Panel',
|
|
28
|
+
pluginKind: 'BertPanel1',
|
|
29
|
+
value: {},
|
|
30
|
+
onChange: jest.fn()
|
|
31
|
+
});
|
|
32
|
+
const queryTab = await screen.findByLabelText('Query');
|
|
33
|
+
expect(queryTab).toBeInTheDocument();
|
|
34
|
+
const editor = await screen.findByLabelText('BertPanel1 editor');
|
|
35
|
+
expect(editor).toBeInTheDocument();
|
|
36
|
+
const jsonEditor = await screen.findByLabelText('JSON');
|
|
37
|
+
expect(jsonEditor).toBeInTheDocument();
|
|
38
|
+
});
|
|
39
|
+
it('should display other options editor components', async ()=>{
|
|
40
|
+
renderComponent({
|
|
41
|
+
pluginType: 'Panel',
|
|
42
|
+
pluginKind: 'BertPanel2',
|
|
43
|
+
value: {},
|
|
44
|
+
onChange: jest.fn()
|
|
45
|
+
});
|
|
46
|
+
const settingsTab = await screen.findByLabelText('Settings');
|
|
47
|
+
expect(settingsTab).toBeInTheDocument();
|
|
48
|
+
const editor = await screen.findByLabelText('BertPanel2 editor');
|
|
49
|
+
expect(editor).toBeInTheDocument();
|
|
50
|
+
const customTab = await screen.findByLabelText('Custom Tab');
|
|
51
|
+
expect(customTab).toBeInTheDocument();
|
|
52
|
+
const jsonEditor = await screen.findByLabelText('JSON');
|
|
53
|
+
expect(jsonEditor).toBeInTheDocument();
|
|
30
54
|
});
|
|
31
|
-
const editor = await screen.findByLabelText('BertPanel1 editor');
|
|
32
|
-
expect(editor).toBeInTheDocument();
|
|
33
55
|
});
|
|
34
56
|
it('propagates value changes', async ()=>{
|
|
35
57
|
const onChange = jest.fn();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/components/PluginSpecEditor.test.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 userEvent from '@testing-library/user-event';\nimport { screen } from '@testing-library/react';\nimport { renderWithContext } from '../test';\nimport { PluginSpecEditor, PluginSpecEditorProps } from './PluginSpecEditor';\n\ndescribe('PluginSpecEditor', () => {\n const renderComponent = (props: PluginSpecEditorProps) => {\n renderWithContext(<PluginSpecEditor {...props} />);\n };\n\n
|
|
1
|
+
{"version":3,"sources":["../../src/components/PluginSpecEditor.test.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 userEvent from '@testing-library/user-event';\nimport { screen } from '@testing-library/react';\nimport { renderWithContext } from '../test';\nimport { PluginSpecEditor, PluginSpecEditorProps } from './PluginSpecEditor';\n\ndescribe('PluginSpecEditor', () => {\n const renderComponent = (props: PluginSpecEditorProps) => {\n renderWithContext(<PluginSpecEditor {...props} />);\n };\n\n describe('Panel plugin', () => {\n it('should show query and json editors', async () => {\n renderComponent({ pluginType: 'Panel', pluginKind: 'BertPanel1', value: {}, onChange: jest.fn() });\n const queryTab = await screen.findByLabelText('Query');\n expect(queryTab).toBeInTheDocument();\n const editor = await screen.findByLabelText('BertPanel1 editor');\n expect(editor).toBeInTheDocument();\n const jsonEditor = await screen.findByLabelText('JSON');\n expect(jsonEditor).toBeInTheDocument();\n });\n\n it('should display other options editor components', async () => {\n renderComponent({ pluginType: 'Panel', pluginKind: 'BertPanel2', value: {}, onChange: jest.fn() });\n const settingsTab = await screen.findByLabelText('Settings');\n expect(settingsTab).toBeInTheDocument();\n const editor = await screen.findByLabelText('BertPanel2 editor');\n expect(editor).toBeInTheDocument();\n const customTab = await screen.findByLabelText('Custom Tab');\n expect(customTab).toBeInTheDocument();\n const jsonEditor = await screen.findByLabelText('JSON');\n expect(jsonEditor).toBeInTheDocument();\n });\n });\n\n it('propagates value changes', async () => {\n const onChange = jest.fn();\n renderComponent({ pluginType: 'Panel', pluginKind: 'BertPanel1', value: { option1: 'Option1Value' }, onChange });\n\n const editor = await screen.findByLabelText('BertPanel1 editor');\n expect(editor).toHaveValue('Option1Value');\n userEvent.clear(editor);\n expect(onChange).toHaveBeenCalledWith({ option1: '' });\n });\n\n it('shows an error if plugin fails to load', async () => {\n renderComponent({ pluginType: 'Variable', pluginKind: 'DoesNotExist', value: {}, onChange: jest.fn() });\n const errorAlert = await screen.findByRole('alert');\n expect(errorAlert).toHaveTextContent(/doesnotexist/i);\n });\n});\n"],"names":["userEvent","screen","renderWithContext","PluginSpecEditor","describe","renderComponent","props","it","pluginType","pluginKind","value","onChange","jest","fn","queryTab","findByLabelText","expect","toBeInTheDocument","editor","jsonEditor","settingsTab","customTab","option1","toHaveValue","clear","toHaveBeenCalledWith","errorAlert","findByRole","toHaveTextContent"],"mappings":"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"}
|
package/dist/model/panels.d.ts
CHANGED
|
@@ -1,11 +1,23 @@
|
|
|
1
|
-
/// <reference types="react" />
|
|
2
1
|
import { UnknownSpec } from '@perses-dev/core';
|
|
3
|
-
import
|
|
2
|
+
import React from 'react';
|
|
3
|
+
import { OptionsEditorTab } from '../components';
|
|
4
|
+
import { OptionsEditorProps, Plugin } from './plugin-base';
|
|
5
|
+
export declare type PanelOptionsEditorComponent<T> = Pick<OptionsEditorTab, 'label'> & {
|
|
6
|
+
content: React.ComponentType<OptionsEditorProps<T>>;
|
|
7
|
+
};
|
|
4
8
|
/**
|
|
5
9
|
* Plugin the provides custom visualizations inside of a Panel.
|
|
6
10
|
*/
|
|
7
11
|
export interface PanelPlugin<Spec = UnknownSpec> extends Plugin<Spec> {
|
|
8
12
|
PanelComponent: React.ComponentType<PanelProps<Spec>>;
|
|
13
|
+
/**
|
|
14
|
+
* React component for the content of "Query" tab
|
|
15
|
+
*/
|
|
16
|
+
PanelQueryEditorComponent?: React.ComponentType<OptionsEditorProps<Spec>>;
|
|
17
|
+
/**
|
|
18
|
+
* React components for custom tabs
|
|
19
|
+
*/
|
|
20
|
+
panelOptionsEditorComponents?: Array<PanelOptionsEditorComponent<Spec>>;
|
|
9
21
|
}
|
|
10
22
|
/**
|
|
11
23
|
* The props provided by Perses to a panel plugin's PanelComponent.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../src/model/panels.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"panels.d.ts","sourceRoot":"","sources":["../../src/model/panels.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AAE3D,oBAAY,2BAA2B,CAAC,CAAC,IAAI,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,GAAG;IAC7E,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC;CACrD,CAAC;AACF;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,IAAI,GAAG,WAAW,CAAE,SAAQ,MAAM,CAAC,IAAI,CAAC;IACnE,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACtD;;OAEG;IACH,yBAAyB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E;;OAEG;IACH,4BAA4B,CAAC,EAAE,KAAK,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,CAAC;CACzE;AAED;;GAEG;AACH,MAAM,WAAW,UAAU,CAAC,IAAI;IAC9B,IAAI,EAAE,IAAI,CAAC;IACX,iBAAiB,CAAC,EAAE;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH"}
|
package/dist/model/panels.js
CHANGED
|
@@ -10,6 +10,6 @@
|
|
|
10
10
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
11
11
|
// See the License for the specific language governing permissions and
|
|
12
12
|
// limitations under the License.
|
|
13
|
-
|
|
13
|
+
import React from 'react';
|
|
14
14
|
|
|
15
15
|
//# sourceMappingURL=panels.js.map
|
package/dist/model/panels.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/model/panels.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 { UnknownSpec } from '@perses-dev/core';\nimport { Plugin } from './plugin-base';\n\n/**\n * Plugin the provides custom visualizations inside of a Panel.\n */\nexport interface PanelPlugin<Spec = UnknownSpec> extends Plugin<Spec> {\n PanelComponent: React.ComponentType<PanelProps<Spec>>;\n}\n\n/**\n * The props provided by Perses to a panel plugin's PanelComponent.\n */\nexport interface PanelProps<Spec> {\n spec: Spec;\n contentDimensions?: {\n width: number;\n height: number;\n };\n}\n"],"names":[],"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;
|
|
1
|
+
{"version":3,"sources":["../../src/model/panels.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 { UnknownSpec } from '@perses-dev/core';\nimport React from 'react';\nimport { OptionsEditorTab } from '../components';\nimport { OptionsEditorProps, Plugin } from './plugin-base';\n\nexport type PanelOptionsEditorComponent<T> = Pick<OptionsEditorTab, 'label'> & {\n content: React.ComponentType<OptionsEditorProps<T>>;\n};\n/**\n * Plugin the provides custom visualizations inside of a Panel.\n */\nexport interface PanelPlugin<Spec = UnknownSpec> extends Plugin<Spec> {\n PanelComponent: React.ComponentType<PanelProps<Spec>>;\n /**\n * React component for the content of \"Query\" tab\n */\n PanelQueryEditorComponent?: React.ComponentType<OptionsEditorProps<Spec>>;\n /**\n * React components for custom tabs\n */\n panelOptionsEditorComponents?: Array<PanelOptionsEditorComponent<Spec>>;\n}\n\n/**\n * The props provided by Perses to a panel plugin's PanelComponent.\n */\nexport interface PanelProps<Spec> {\n spec: Spec;\n contentDimensions?: {\n width: number;\n height: number;\n };\n}\n"],"names":["React"],"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,OAAOA,KAAK,MAAM,OAAO,CAAC"}
|
|
@@ -6,7 +6,7 @@ export interface Plugin<Spec> {
|
|
|
6
6
|
/**
|
|
7
7
|
* React component for editing the plugin's options in the UI.
|
|
8
8
|
*/
|
|
9
|
-
OptionsEditorComponent
|
|
9
|
+
OptionsEditorComponent?: React.ComponentType<OptionsEditorProps<Spec>>;
|
|
10
10
|
/**
|
|
11
11
|
* Callback for creating the initial options for the plugin.
|
|
12
12
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin-base.d.ts","sourceRoot":"","sources":["../../src/model/plugin-base.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,MAAM,CAAC,IAAI;IAC1B;;OAEG;IACH,sBAAsB,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"plugin-base.d.ts","sourceRoot":"","sources":["../../src/model/plugin-base.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B;;GAEG;AACH,MAAM,WAAW,MAAM,CAAC,IAAI;IAC1B;;OAEG;IACH,sBAAsB,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAC;IAEvE;;OAEG;IACH,oBAAoB,EAAE,MAAM,IAAI,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,IAAI;IAGtC,KAAK,EAAE,IAAI,CAAC;IACZ,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAChC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/model/plugin-base.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 React from 'react';\n\n/**\n * Base type of all plugin implementations.\n */\nexport interface Plugin<Spec> {\n /**\n * React component for editing the plugin's options in the UI.\n */\n OptionsEditorComponent
|
|
1
|
+
{"version":3,"sources":["../../src/model/plugin-base.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 React from 'react';\n\n/**\n * Base type of all plugin implementations.\n */\nexport interface Plugin<Spec> {\n /**\n * React component for editing the plugin's options in the UI.\n */\n OptionsEditorComponent?: React.ComponentType<OptionsEditorProps<Spec>>;\n\n /**\n * Callback for creating the initial options for the plugin.\n */\n createInitialOptions: () => Spec;\n}\n\n/**\n * Common props passed to options editor components.\n */\nexport interface OptionsEditorProps<Spec> {\n // TODO: These are temporary and may not actually make sense, so replace\n // with whatever makes sense as visual editing evolves\n value: Spec;\n onChange: (next: Spec) => void;\n}\n"],"names":["React"],"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,KAAK,MAAM,OAAO,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/test/test-plugins/bert/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAgBvD,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/test/test-plugins/bert/index.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAG7C,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAgBvD,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,WAAW,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CA2BvD,CAAC"}
|
|
@@ -14,7 +14,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
14
14
|
// Dummy plugins to test loading
|
|
15
15
|
export const BertPanel1 = {
|
|
16
16
|
PanelComponent: ()=>null,
|
|
17
|
-
|
|
17
|
+
PanelQueryEditorComponent: function BertPanel1Editor({ value , onChange }) {
|
|
18
18
|
return /*#__PURE__*/ _jsxs("div", {
|
|
19
19
|
children: [
|
|
20
20
|
/*#__PURE__*/ _jsx("label", {
|
|
@@ -39,25 +39,38 @@ export const BertPanel1 = {
|
|
|
39
39
|
};
|
|
40
40
|
export const BertPanel2 = {
|
|
41
41
|
PanelComponent: ()=>null,
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
children:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
42
|
+
panelOptionsEditorComponents: [
|
|
43
|
+
{
|
|
44
|
+
label: 'Settings',
|
|
45
|
+
content: function BertPanel2Editor({ value , onChange }) {
|
|
46
|
+
return /*#__PURE__*/ _jsxs("div", {
|
|
47
|
+
children: [
|
|
48
|
+
/*#__PURE__*/ _jsx("label", {
|
|
49
|
+
htmlFor: "editor-input",
|
|
50
|
+
children: "BertPanel2 editor"
|
|
51
|
+
}),
|
|
52
|
+
/*#__PURE__*/ _jsx("input", {
|
|
53
|
+
type: "text",
|
|
54
|
+
id: "editor-input",
|
|
55
|
+
value: value.option2,
|
|
56
|
+
onChange: (e)=>onChange({
|
|
57
|
+
...value,
|
|
58
|
+
option2: e.target.value
|
|
59
|
+
})
|
|
56
60
|
})
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
]
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
label: 'Custom Tab',
|
|
67
|
+
content: function Editor() {
|
|
68
|
+
return /*#__PURE__*/ _jsx("div", {
|
|
69
|
+
children: "custom content"
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
],
|
|
61
74
|
createInitialOptions: ()=>({
|
|
62
75
|
option2: ''
|
|
63
76
|
})
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/test/test-plugins/bert/index.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 { PanelPlugin } from '../../../model';\n\n// Dummy plugins to test loading\nexport const BertPanel1: PanelPlugin<{ option1: string }> = {\n PanelComponent: () => null,\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/test/test-plugins/bert/index.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 { PanelPlugin } from '../../../model';\n\n// Dummy plugins to test loading\nexport const BertPanel1: PanelPlugin<{ option1: string }> = {\n PanelComponent: () => null,\n PanelQueryEditorComponent: function BertPanel1Editor({ value, onChange }) {\n return (\n <div>\n <label htmlFor=\"editor-input\">BertPanel1 editor</label>\n <input\n type=\"text\"\n id=\"editor-input\"\n value={value.option1}\n onChange={(e) => onChange({ ...value, option1: e.target.value })}\n />\n </div>\n );\n },\n createInitialOptions: () => ({ option1: '' }),\n};\n\nexport const BertPanel2: PanelPlugin<{ option2: string }> = {\n PanelComponent: () => null,\n panelOptionsEditorComponents: [\n {\n label: 'Settings',\n content: function BertPanel2Editor({ value, onChange }) {\n return (\n <div>\n <label htmlFor=\"editor-input\">BertPanel2 editor</label>\n <input\n type=\"text\"\n id=\"editor-input\"\n value={value.option2}\n onChange={(e) => onChange({ ...value, option2: e.target.value })}\n />\n </div>\n );\n },\n },\n {\n label: 'Custom Tab',\n content: function Editor() {\n return <div>custom content</div>;\n },\n },\n ],\n createInitialOptions: () => ({ option2: '' }),\n};\n"],"names":["BertPanel1","PanelComponent","PanelQueryEditorComponent","BertPanel1Editor","value","onChange","div","label","htmlFor","input","type","id","option1","e","target","createInitialOptions","BertPanel2","panelOptionsEditorComponents","content","BertPanel2Editor","option2","Editor"],"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;AAEA,gCAAgC;AAChC,OAAO,MAAMA,UAAU,GAAqC;IAC1DC,cAAc,EAAE,IAAM,IAAI;IAC1BC,yBAAyB,EAAE,SAASC,gBAAgB,CAAC,EAAEC,KAAK,CAAA,EAAEC,QAAQ,CAAA,EAAE,EAAE;QACxE,qBACE,MAACC,KAAG;;8BACF,KAACC,OAAK;oBAACC,OAAO,EAAC,cAAc;8BAAC,mBAAiB;kBAAQ;8BACvD,KAACC,OAAK;oBACJC,IAAI,EAAC,MAAM;oBACXC,EAAE,EAAC,cAAc;oBACjBP,KAAK,EAAEA,KAAK,CAACQ,OAAO;oBACpBP,QAAQ,EAAE,CAACQ,CAAC,GAAKR,QAAQ,CAAC;4BAAE,GAAGD,KAAK;4BAAEQ,OAAO,EAAEC,CAAC,CAACC,MAAM,CAACV,KAAK;yBAAE,CAAC;kBAChE;;UACE,CACN;IACJ,CAAC;IACDW,oBAAoB,EAAE,IAAO,CAAA;YAAEH,OAAO,EAAE,EAAE;SAAE,CAAA,AAAC;CAC9C,CAAC;AAEF,OAAO,MAAMI,UAAU,GAAqC;IAC1Df,cAAc,EAAE,IAAM,IAAI;IAC1BgB,4BAA4B,EAAE;QAC5B;YACEV,KAAK,EAAE,UAAU;YACjBW,OAAO,EAAE,SAASC,gBAAgB,CAAC,EAAEf,KAAK,CAAA,EAAEC,QAAQ,CAAA,EAAE,EAAE;gBACtD,qBACE,MAACC,KAAG;;sCACF,KAACC,OAAK;4BAACC,OAAO,EAAC,cAAc;sCAAC,mBAAiB;0BAAQ;sCACvD,KAACC,OAAK;4BACJC,IAAI,EAAC,MAAM;4BACXC,EAAE,EAAC,cAAc;4BACjBP,KAAK,EAAEA,KAAK,CAACgB,OAAO;4BACpBf,QAAQ,EAAE,CAACQ,CAAC,GAAKR,QAAQ,CAAC;oCAAE,GAAGD,KAAK;oCAAEgB,OAAO,EAAEP,CAAC,CAACC,MAAM,CAACV,KAAK;iCAAE,CAAC;0BAChE;;kBACE,CACN;YACJ,CAAC;SACF;QACD;YACEG,KAAK,EAAE,YAAY;YACnBW,OAAO,EAAE,SAASG,MAAM,GAAG;gBACzB,qBAAO,KAACf,KAAG;8BAAC,gBAAc;kBAAM,CAAC;YACnC,CAAC;SACF;KACF;IACDS,oBAAoB,EAAE,IAAO,CAAA;YAAEK,OAAO,EAAE,EAAE;SAAE,CAAA,AAAC;CAC9C,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@perses-dev/plugin-system",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.23.0",
|
|
4
4
|
"description": "The plugin feature in Pereses",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/perses/perses/blob/main/README.md",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"lint:fix": "eslint --fix src --ext .ts,.tsx"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@perses-dev/components": "0.
|
|
31
|
-
"@perses-dev/core": "0.
|
|
30
|
+
"@perses-dev/components": "0.23.0",
|
|
31
|
+
"@perses-dev/core": "0.23.0",
|
|
32
32
|
"immer": "^9.0.15",
|
|
33
33
|
"use-immer": "^0.7.0",
|
|
34
34
|
"use-query-params": "^2.1.2"
|