@perses-dev/dashboards 0.50.1 → 0.51.0-beta.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 (189) hide show
  1. package/dist/cjs/components/Dashboard/Dashboard.js +1 -3
  2. package/dist/cjs/components/DashboardToolbar/DashboardToolbar.js +3 -3
  3. package/dist/cjs/components/Datasources/DatasourceEditor.js +2 -5
  4. package/dist/cjs/components/Datasources/EditDatasourcesButton.js +2 -5
  5. package/dist/cjs/components/DeletePanelDialog/DeletePanelDialog.js +2 -0
  6. package/dist/cjs/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +4 -3
  7. package/dist/cjs/components/DownloadButton/DownloadButton.js +135 -29
  8. package/dist/cjs/components/EditJsonDialog/EditJsonDialog.js +5 -7
  9. package/dist/cjs/components/EmptyDashboard/EmptyDashboard.js +1 -1
  10. package/dist/cjs/components/GridLayout/GridItemContent.js +4 -3
  11. package/dist/cjs/components/GridLayout/GridLayout.js +5 -6
  12. package/dist/cjs/components/GridLayout/GridTitle.js +3 -3
  13. package/dist/cjs/components/Panel/HeaderIconButton.js +27 -0
  14. package/dist/cjs/components/Panel/Panel.js +16 -10
  15. package/dist/cjs/components/Panel/PanelActions.js +365 -0
  16. package/dist/cjs/components/Panel/PanelContent.js +59 -13
  17. package/dist/cjs/components/Panel/PanelHeader.js +14 -141
  18. package/dist/cjs/components/Panel/PanelLinks.js +5 -6
  19. package/dist/cjs/components/Panel/PanelPluginLoader.js +56 -0
  20. package/dist/cjs/components/Panel/index.js +1 -0
  21. package/dist/cjs/components/PanelDrawer/PanelDrawer.js +9 -6
  22. package/dist/cjs/components/PanelDrawer/PanelEditorForm.js +17 -35
  23. package/dist/cjs/components/PanelDrawer/PanelPreview.js +4 -5
  24. package/dist/cjs/components/PanelGroupDialog/PanelGroupDialog.js +1 -1
  25. package/dist/cjs/components/QuerySummaryTable/QuerySummaryTable.js +3 -5
  26. package/dist/cjs/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +2 -4
  27. package/dist/cjs/components/Variables/BuiltinVariableAccordions.js +5 -12
  28. package/dist/cjs/components/Variables/Variable.js +30 -36
  29. package/dist/cjs/components/Variables/VariableEditor.js +14 -23
  30. package/dist/cjs/components/Variables/VariableList.js +4 -6
  31. package/dist/cjs/constants/styles.js +12 -0
  32. package/dist/cjs/constants/user-interface-text.js +1 -1
  33. package/dist/cjs/context/DashboardProvider/DashboardProvider.js +5 -6
  34. package/dist/cjs/context/DashboardProvider/DashboardProviderWithQueryParams.js +1 -1
  35. package/dist/cjs/context/DashboardProvider/common.js +2 -2
  36. package/dist/cjs/context/DashboardProvider/dashboard-provider-api.js +13 -3
  37. package/dist/cjs/context/DashboardProvider/delete-panel-slice.js +1 -2
  38. package/dist/cjs/context/DashboardProvider/panel-editor-slice.js +3 -6
  39. package/dist/cjs/context/DashboardProvider/panel-group-editor-slice.js +1 -2
  40. package/dist/cjs/context/DashboardProvider/panel-group-slice.js +3 -4
  41. package/dist/cjs/context/DashboardProvider/view-panel-slice.js +1 -2
  42. package/dist/cjs/context/DatasourceStoreProvider.js +15 -22
  43. package/dist/cjs/context/VariableProvider/VariableProvider.js +8 -11
  44. package/dist/cjs/context/VariableProvider/hydrationUtils.js +3 -6
  45. package/dist/cjs/context/VariableProvider/utils.js +2 -2
  46. package/dist/cjs/stories/decorators/WithDashboard.js +1 -1
  47. package/dist/cjs/stories/decorators/WithDatasourceStore.js +1 -1
  48. package/dist/cjs/stories/decorators/WithVariables.js +1 -1
  49. package/dist/cjs/test/plugin-registry.js +8 -3
  50. package/dist/cjs/test/render.js +13 -11
  51. package/dist/cjs/views/ViewDashboard/DashboardApp.js +4 -3
  52. package/dist/cjs/views/ViewDashboard/ViewDashboard.js +5 -5
  53. package/dist/components/Dashboard/Dashboard.js +1 -3
  54. package/dist/components/Dashboard/Dashboard.js.map +1 -1
  55. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts +2 -0
  56. package/dist/components/DashboardToolbar/DashboardToolbar.d.ts.map +1 -1
  57. package/dist/components/DashboardToolbar/DashboardToolbar.js +3 -3
  58. package/dist/components/DashboardToolbar/DashboardToolbar.js.map +1 -1
  59. package/dist/components/Datasources/DatasourceEditor.js +2 -5
  60. package/dist/components/Datasources/DatasourceEditor.js.map +1 -1
  61. package/dist/components/Datasources/EditDatasourcesButton.js +2 -5
  62. package/dist/components/Datasources/EditDatasourcesButton.js.map +1 -1
  63. package/dist/components/DeletePanelDialog/DeletePanelDialog.js +3 -1
  64. package/dist/components/DeletePanelDialog/DeletePanelDialog.js.map +1 -1
  65. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.d.ts.map +1 -1
  66. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js +5 -4
  67. package/dist/components/DeletePanelGroupDialog/DeletePanelGroupDialog.js.map +1 -1
  68. package/dist/components/DownloadButton/DownloadButton.d.ts +1 -5
  69. package/dist/components/DownloadButton/DownloadButton.d.ts.map +1 -1
  70. package/dist/components/DownloadButton/DownloadButton.js +94 -29
  71. package/dist/components/DownloadButton/DownloadButton.js.map +1 -1
  72. package/dist/components/EditJsonDialog/EditJsonDialog.js +5 -7
  73. package/dist/components/EditJsonDialog/EditJsonDialog.js.map +1 -1
  74. package/dist/components/EmptyDashboard/EmptyDashboard.js +1 -1
  75. package/dist/components/EmptyDashboard/EmptyDashboard.js.map +1 -1
  76. package/dist/components/GridLayout/GridItemContent.d.ts.map +1 -1
  77. package/dist/components/GridLayout/GridItemContent.js +5 -4
  78. package/dist/components/GridLayout/GridItemContent.js.map +1 -1
  79. package/dist/components/GridLayout/GridLayout.js +6 -7
  80. package/dist/components/GridLayout/GridLayout.js.map +1 -1
  81. package/dist/components/GridLayout/GridTitle.js +3 -3
  82. package/dist/components/GridLayout/GridTitle.js.map +1 -1
  83. package/dist/components/Panel/HeaderIconButton.d.ts +5 -0
  84. package/dist/components/Panel/HeaderIconButton.d.ts.map +1 -0
  85. package/dist/components/Panel/HeaderIconButton.js +19 -0
  86. package/dist/components/Panel/HeaderIconButton.js.map +1 -0
  87. package/dist/components/Panel/Panel.d.ts +7 -2
  88. package/dist/components/Panel/Panel.d.ts.map +1 -1
  89. package/dist/components/Panel/Panel.js +22 -11
  90. package/dist/components/Panel/Panel.js.map +1 -1
  91. package/dist/components/Panel/PanelActions.d.ts +22 -0
  92. package/dist/components/Panel/PanelActions.d.ts.map +1 -0
  93. package/dist/components/Panel/PanelActions.js +352 -0
  94. package/dist/components/Panel/PanelActions.js.map +1 -0
  95. package/dist/components/Panel/PanelContent.d.ts +5 -4
  96. package/dist/components/Panel/PanelContent.d.ts.map +1 -1
  97. package/dist/components/Panel/PanelContent.js +61 -15
  98. package/dist/components/Panel/PanelContent.js.map +1 -1
  99. package/dist/components/Panel/PanelHeader.d.ts +7 -11
  100. package/dist/components/Panel/PanelHeader.d.ts.map +1 -1
  101. package/dist/components/Panel/PanelHeader.js +18 -140
  102. package/dist/components/Panel/PanelHeader.js.map +1 -1
  103. package/dist/components/Panel/PanelLinks.js +5 -6
  104. package/dist/components/Panel/PanelLinks.js.map +1 -1
  105. package/dist/components/Panel/PanelPluginLoader.d.ts +13 -0
  106. package/dist/components/Panel/PanelPluginLoader.d.ts.map +1 -0
  107. package/dist/components/Panel/PanelPluginLoader.js +51 -0
  108. package/dist/components/Panel/PanelPluginLoader.js.map +1 -0
  109. package/dist/components/Panel/index.d.ts +1 -0
  110. package/dist/components/Panel/index.d.ts.map +1 -1
  111. package/dist/components/Panel/index.js +1 -0
  112. package/dist/components/Panel/index.js.map +1 -1
  113. package/dist/components/PanelDrawer/PanelDrawer.d.ts.map +1 -1
  114. package/dist/components/PanelDrawer/PanelDrawer.js +10 -7
  115. package/dist/components/PanelDrawer/PanelDrawer.js.map +1 -1
  116. package/dist/components/PanelDrawer/PanelEditorForm.js +17 -35
  117. package/dist/components/PanelDrawer/PanelEditorForm.js.map +1 -1
  118. package/dist/components/PanelDrawer/PanelPreview.js +4 -5
  119. package/dist/components/PanelDrawer/PanelPreview.js.map +1 -1
  120. package/dist/components/PanelGroupDialog/PanelGroupDialog.js +1 -1
  121. package/dist/components/PanelGroupDialog/PanelGroupDialog.js.map +1 -1
  122. package/dist/components/QuerySummaryTable/QuerySummaryTable.js +3 -5
  123. package/dist/components/QuerySummaryTable/QuerySummaryTable.js.map +1 -1
  124. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js +2 -4
  125. package/dist/components/SaveChangesConfirmationDialog/SaveChangesConfirmationDialog.js.map +1 -1
  126. package/dist/components/Variables/BuiltinVariableAccordions.js +5 -12
  127. package/dist/components/Variables/BuiltinVariableAccordions.js.map +1 -1
  128. package/dist/components/Variables/Variable.js +30 -36
  129. package/dist/components/Variables/Variable.js.map +1 -1
  130. package/dist/components/Variables/VariableEditor.js +14 -23
  131. package/dist/components/Variables/VariableEditor.js.map +1 -1
  132. package/dist/components/Variables/VariableList.js +4 -6
  133. package/dist/components/Variables/VariableList.js.map +1 -1
  134. package/dist/constants/styles.d.ts +3 -0
  135. package/dist/constants/styles.d.ts.map +1 -1
  136. package/dist/constants/styles.js +3 -0
  137. package/dist/constants/styles.js.map +1 -1
  138. package/dist/constants/user-interface-text.d.ts +1 -1
  139. package/dist/constants/user-interface-text.d.ts.map +1 -1
  140. package/dist/constants/user-interface-text.js +1 -1
  141. package/dist/constants/user-interface-text.js.map +1 -1
  142. package/dist/context/DashboardProvider/DashboardProvider.js +5 -6
  143. package/dist/context/DashboardProvider/DashboardProvider.js.map +1 -1
  144. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js +1 -1
  145. package/dist/context/DashboardProvider/DashboardProviderWithQueryParams.js.map +1 -1
  146. package/dist/context/DashboardProvider/common.js +2 -2
  147. package/dist/context/DashboardProvider/common.js.map +1 -1
  148. package/dist/context/DashboardProvider/dashboard-provider-api.d.ts +11 -2
  149. package/dist/context/DashboardProvider/dashboard-provider-api.d.ts.map +1 -1
  150. package/dist/context/DashboardProvider/dashboard-provider-api.js +13 -4
  151. package/dist/context/DashboardProvider/dashboard-provider-api.js.map +1 -1
  152. package/dist/context/DashboardProvider/delete-panel-slice.js +1 -2
  153. package/dist/context/DashboardProvider/delete-panel-slice.js.map +1 -1
  154. package/dist/context/DashboardProvider/panel-editor-slice.js +3 -6
  155. package/dist/context/DashboardProvider/panel-editor-slice.js.map +1 -1
  156. package/dist/context/DashboardProvider/panel-group-editor-slice.js +1 -2
  157. package/dist/context/DashboardProvider/panel-group-editor-slice.js.map +1 -1
  158. package/dist/context/DashboardProvider/panel-group-slice.js +3 -4
  159. package/dist/context/DashboardProvider/panel-group-slice.js.map +1 -1
  160. package/dist/context/DashboardProvider/view-panel-slice.js +1 -2
  161. package/dist/context/DashboardProvider/view-panel-slice.js.map +1 -1
  162. package/dist/context/DatasourceStoreProvider.js +15 -22
  163. package/dist/context/DatasourceStoreProvider.js.map +1 -1
  164. package/dist/context/VariableProvider/VariableProvider.js +8 -11
  165. package/dist/context/VariableProvider/VariableProvider.js.map +1 -1
  166. package/dist/context/VariableProvider/hydrationUtils.js +3 -6
  167. package/dist/context/VariableProvider/hydrationUtils.js.map +1 -1
  168. package/dist/context/VariableProvider/utils.js +2 -2
  169. package/dist/context/VariableProvider/utils.js.map +1 -1
  170. package/dist/stories/decorators/WithDashboard.js +1 -1
  171. package/dist/stories/decorators/WithDashboard.js.map +1 -1
  172. package/dist/stories/decorators/WithDatasourceStore.js +1 -1
  173. package/dist/stories/decorators/WithDatasourceStore.js.map +1 -1
  174. package/dist/stories/decorators/WithVariables.js +1 -1
  175. package/dist/stories/decorators/WithVariables.js.map +1 -1
  176. package/dist/test/plugin-registry.d.ts.map +1 -1
  177. package/dist/test/plugin-registry.js +8 -3
  178. package/dist/test/plugin-registry.js.map +1 -1
  179. package/dist/test/render.d.ts.map +1 -1
  180. package/dist/test/render.js +9 -7
  181. package/dist/test/render.js.map +1 -1
  182. package/dist/views/ViewDashboard/DashboardApp.d.ts +2 -0
  183. package/dist/views/ViewDashboard/DashboardApp.d.ts.map +1 -1
  184. package/dist/views/ViewDashboard/DashboardApp.js +4 -3
  185. package/dist/views/ViewDashboard/DashboardApp.js.map +1 -1
  186. package/dist/views/ViewDashboard/ViewDashboard.d.ts.map +1 -1
  187. package/dist/views/ViewDashboard/ViewDashboard.js +5 -5
  188. package/dist/views/ViewDashboard/ViewDashboard.js.map +1 -1
  189. package/package.json +8 -7
@@ -29,12 +29,10 @@ const _GridLayout = require("../GridLayout");
29
29
  const _EmptyDashboard = require("../EmptyDashboard");
30
30
  const HEADER_HEIGHT = 165; // Approximate height of the header in dashboard view (including the navbar and variables toolbar)
31
31
  function Dashboard({ emptyDashboardProps, panelOptions, ...boxProps }) {
32
- var _boxRef_current;
33
32
  const panelGroupIds = (0, _context.usePanelGroupIds)();
34
33
  const boxRef = (0, _react.useRef)(null);
35
34
  const isEmpty = !panelGroupIds.length;
36
- var _boxRef_current_getBoundingClientRect_top;
37
- const dashboardTopPosition = (_boxRef_current_getBoundingClientRect_top = (_boxRef_current = boxRef.current) === null || _boxRef_current === void 0 ? void 0 : _boxRef_current.getBoundingClientRect().top) !== null && _boxRef_current_getBoundingClientRect_top !== void 0 ? _boxRef_current_getBoundingClientRect_top : HEADER_HEIGHT;
35
+ const dashboardTopPosition = boxRef.current?.getBoundingClientRect().top ?? HEADER_HEIGHT;
38
36
  const panelFullHeight = window.innerHeight - dashboardTopPosition - window.scrollY;
39
37
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
40
38
  ...boxProps,
@@ -35,7 +35,7 @@ const _EditJsonButton = require("../EditJsonButton");
35
35
  const _SaveDashboardButton = require("../SaveDashboardButton");
36
36
  const _DashboardStickyToolbar = require("../DashboardStickyToolbar");
37
37
  const DashboardToolbar = (props)=>{
38
- const { dashboardName, dashboardTitleComponent, initialVariableIsSticky, isReadonly, onEditButtonClick, onCancelButtonClick, onSave } = props;
38
+ const { dashboardName, dashboardTitleComponent, initialVariableIsSticky, isReadonly, isVariableEnabled, isDatasourceEnabled, onEditButtonClick, onCancelButtonClick, onSave } = props;
39
39
  const { isEditMode } = (0, _context.useEditMode)();
40
40
  const isBiggerThanSm = (0, _material.useMediaQuery)((0, _material.useTheme)().breakpoints.up('sm'));
41
41
  const isBiggerThanMd = (0, _material.useMediaQuery)((0, _material.useTheme)().breakpoints.up('md'));
@@ -76,8 +76,8 @@ const DashboardToolbar = (props)=>{
76
76
  ml: 1,
77
77
  whiteSpace: "nowrap",
78
78
  children: [
79
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_Variables.EditVariablesButton, {}),
80
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_Datasources.EditDatasourcesButton, {}),
79
+ isVariableEnabled && /*#__PURE__*/ (0, _jsxruntime.jsx)(_Variables.EditVariablesButton, {}),
80
+ isDatasourceEnabled && /*#__PURE__*/ (0, _jsxruntime.jsx)(_Datasources.EditDatasourcesButton, {}),
81
81
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_AddPanelButton.AddPanelButton, {}),
82
82
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_AddGroupButton.AddGroupButton, {})
83
83
  ]
@@ -77,10 +77,9 @@ function DatasourceEditor(props) {
77
77
  };
78
78
  const editDatasource = (name)=>{
79
79
  setDatasourceFormAction('update');
80
- var _datasources_name;
81
80
  setDatasourceEdit({
82
81
  name: name,
83
- spec: (_datasources_name = datasources[name]) !== null && _datasources_name !== void 0 ? _datasources_name : defaultSpec
82
+ spec: datasources[name] ?? defaultSpec
84
83
  });
85
84
  };
86
85
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_jsxruntime.Fragment, {
@@ -176,8 +175,6 @@ function DatasourceEditor(props) {
176
175
  }),
177
176
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TableBody, {
178
177
  children: Object.entries(datasources).map(([name, spec])=>{
179
- var _spec_display;
180
- var _spec_display_description;
181
178
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.TableRow, {
182
179
  children: [
183
180
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TableCell, {
@@ -192,7 +189,7 @@ function DatasourceEditor(props) {
192
189
  children: spec.plugin.kind
193
190
  }),
194
191
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.TableCell, {
195
- children: (_spec_display_description = (_spec_display = spec.display) === null || _spec_display === void 0 ? void 0 : _spec_display.description) !== null && _spec_display_description !== void 0 ? _spec_display_description : ''
192
+ children: spec.display?.description ?? ''
196
193
  }),
197
194
  /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.TableCell, {
198
195
  align: "right",
@@ -49,13 +49,10 @@ function EditDatasourcesButton() {
49
49
  const handleChangeDatasources = (datasources)=>{
50
50
  // Calculates the new list of datasources that are allowed to be used.
51
51
  const newSavedDatasources = Object.keys(datasources).filter((key)=>{
52
- var _datasources_key_plugin, _datasources_key, _savedDatasources_key_plugin, _savedDatasources_key, _datasources_key_plugin_spec, _datasources_key_plugin1, _datasources_key1, _savedDatasources_key_plugin_spec, _savedDatasources_key_plugin1, _savedDatasources_key1;
53
- var _datasources_key_plugin_spec1;
54
52
  // Datasources are allowed to be used if a) they are direct, or b) they are proxied, and their
55
53
  // proxy is the same as what we have saved.
56
- const isDirect = 'directUrl' in ((_datasources_key_plugin_spec1 = (_datasources_key = datasources[key]) === null || _datasources_key === void 0 ? void 0 : (_datasources_key_plugin = _datasources_key.plugin) === null || _datasources_key_plugin === void 0 ? void 0 : _datasources_key_plugin.spec) !== null && _datasources_key_plugin_spec1 !== void 0 ? _datasources_key_plugin_spec1 : {});
57
- var _savedDatasources_key_plugin_spec1;
58
- const isSavedProxy = !isDirect && !('directUrl' in ((_savedDatasources_key_plugin_spec1 = (_savedDatasources_key = savedDatasources[key]) === null || _savedDatasources_key === void 0 ? void 0 : (_savedDatasources_key_plugin = _savedDatasources_key.plugin) === null || _savedDatasources_key_plugin === void 0 ? void 0 : _savedDatasources_key_plugin.spec) !== null && _savedDatasources_key_plugin_spec1 !== void 0 ? _savedDatasources_key_plugin_spec1 : {})) && ((_datasources_key1 = datasources[key]) === null || _datasources_key1 === void 0 ? void 0 : (_datasources_key_plugin1 = _datasources_key1.plugin) === null || _datasources_key_plugin1 === void 0 ? void 0 : (_datasources_key_plugin_spec = _datasources_key_plugin1.spec) === null || _datasources_key_plugin_spec === void 0 ? void 0 : _datasources_key_plugin_spec.proxy) === ((_savedDatasources_key1 = savedDatasources[key]) === null || _savedDatasources_key1 === void 0 ? void 0 : (_savedDatasources_key_plugin1 = _savedDatasources_key1.plugin) === null || _savedDatasources_key_plugin1 === void 0 ? void 0 : (_savedDatasources_key_plugin_spec = _savedDatasources_key_plugin1.spec) === null || _savedDatasources_key_plugin_spec === void 0 ? void 0 : _savedDatasources_key_plugin_spec.proxy);
54
+ const isDirect = 'directUrl' in (datasources[key]?.plugin?.spec ?? {});
55
+ const isSavedProxy = !isDirect && !('directUrl' in (savedDatasources[key]?.plugin?.spec ?? {})) && datasources[key]?.plugin?.spec?.proxy === savedDatasources[key]?.plugin?.spec?.proxy;
59
56
  return isDirect || isSavedProxy;
60
57
  }).reduce((obj, key)=>{
61
58
  obj[key] = datasources[key];
@@ -40,11 +40,13 @@ const DeletePanelDialog = ()=>{
40
40
  };
41
41
  const DeletePanelForm = ({ deletePanelDialog })=>{
42
42
  const { deletePanel, closeDeletePanelDialog } = (0, _context.useDeletePanelDialog)();
43
+ const { setViewPanel } = (0, _context.useViewPanel)();
43
44
  const handleDelete = (e)=>{
44
45
  e.preventDefault();
45
46
  const { panelGroupItemId } = deletePanelDialog;
46
47
  deletePanel(panelGroupItemId);
47
48
  closeDeletePanelDialog();
49
+ setViewPanel(undefined);
48
50
  };
49
51
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)("form", {
50
52
  onSubmit: handleDelete,
@@ -31,7 +31,8 @@ function _interop_require_default(obj) {
31
31
  }
32
32
  const DeletePanelGroupDialog = ()=>{
33
33
  const { deletePanelGroupDialog, closeDeletePanelGroupDialog, deletePanelGroup } = (0, _context.useDeletePanelGroupDialog)();
34
- const panelGroupId = deletePanelGroupDialog === null || deletePanelGroupDialog === void 0 ? void 0 : deletePanelGroupDialog.panelGroupId;
34
+ const { setViewPanel } = (0, _context.useViewPanel)();
35
+ const panelGroupId = deletePanelGroupDialog?.panelGroupId;
35
36
  const handleDelete = (e)=>{
36
37
  e.preventDefault();
37
38
  if (panelGroupId === undefined) {
@@ -39,8 +40,8 @@ const DeletePanelGroupDialog = ()=>{
39
40
  }
40
41
  deletePanelGroup(panelGroupId);
41
42
  closeDeletePanelGroupDialog();
43
+ setViewPanel(undefined);
42
44
  };
43
- var _deletePanelGroupDialog_panelGroupName;
44
45
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Dialog, {
45
46
  open: deletePanelGroupDialog !== undefined,
46
47
  children: [
@@ -67,7 +68,7 @@ const DeletePanelGroupDialog = ()=>{
67
68
  },
68
69
  children: [
69
70
  "Are you sure you want to delete ",
70
- (_deletePanelGroupDialog_panelGroupName = deletePanelGroupDialog === null || deletePanelGroupDialog === void 0 ? void 0 : deletePanelGroupDialog.panelGroupName) !== null && _deletePanelGroupDialog_panelGroupName !== void 0 ? _deletePanelGroupDialog_panelGroupName : 'panel group',
71
+ deletePanelGroupDialog?.panelGroupName ?? 'panel group',
71
72
  "? This will delete all the panels within the group."
72
73
  ]
73
74
  }),
@@ -21,53 +21,159 @@ Object.defineProperty(exports, "DownloadButton", {
21
21
  }
22
22
  });
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
- const _react = require("react");
25
- const _DownloadOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DownloadOutline"));
24
+ const _material = require("@mui/material");
26
25
  const _components = require("@perses-dev/components");
27
- const _constants = require("../../constants");
26
+ const _DownloadOutline = /*#__PURE__*/ _interop_require_default(require("mdi-material-ui/DownloadOutline"));
27
+ const _react = /*#__PURE__*/ _interop_require_wildcard(require("react"));
28
+ const _yaml = require("yaml");
28
29
  const _context = require("../../context");
29
30
  function _interop_require_default(obj) {
30
31
  return obj && obj.__esModule ? obj : {
31
32
  default: obj
32
33
  };
33
34
  }
34
- function DownloadButton({ heightPx }) {
35
+ function _getRequireWildcardCache(nodeInterop) {
36
+ if (typeof WeakMap !== "function") return null;
37
+ var cacheBabelInterop = new WeakMap();
38
+ var cacheNodeInterop = new WeakMap();
39
+ return (_getRequireWildcardCache = function(nodeInterop) {
40
+ return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
41
+ })(nodeInterop);
42
+ }
43
+ function _interop_require_wildcard(obj, nodeInterop) {
44
+ if (!nodeInterop && obj && obj.__esModule) {
45
+ return obj;
46
+ }
47
+ if (obj === null || typeof obj !== "object" && typeof obj !== "function") {
48
+ return {
49
+ default: obj
50
+ };
51
+ }
52
+ var cache = _getRequireWildcardCache(nodeInterop);
53
+ if (cache && cache.has(obj)) {
54
+ return cache.get(obj);
55
+ }
56
+ var newObj = {
57
+ __proto__: null
58
+ };
59
+ var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
60
+ for(var key in obj){
61
+ if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) {
62
+ var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
63
+ if (desc && (desc.get || desc.set)) {
64
+ Object.defineProperty(newObj, key, desc);
65
+ } else {
66
+ newObj[key] = obj[key];
67
+ }
68
+ }
69
+ }
70
+ newObj.default = obj;
71
+ if (cache) {
72
+ cache.set(obj, newObj);
73
+ }
74
+ return newObj;
75
+ }
76
+ function DownloadButton() {
35
77
  const { dashboard } = (0, _context.useDashboard)();
36
78
  const hiddenLinkRef = (0, _react.useRef)(null);
37
- const height = heightPx === undefined ? undefined : `${heightPx}px`;
38
- const onDownloadButtonClick = ()=>{
39
- if (!hiddenLinkRef || !hiddenLinkRef.current) return;
40
- // Create blob URL
41
- const hiddenLinkUrl = URL.createObjectURL(new Blob([
42
- JSON.stringify(dashboard)
43
- ], {
44
- type: 'application/json'
45
- }));
46
- // Simulate click
47
- hiddenLinkRef.current.href = hiddenLinkUrl;
48
- hiddenLinkRef.current.click();
49
- // Remove blob URL (for memory management)
50
- URL.revokeObjectURL(hiddenLinkUrl);
79
+ const [anchorEl, setAnchorEl] = _react.default.useState(null);
80
+ const open = Boolean(anchorEl);
81
+ const handleClick = (event)=>{
82
+ setAnchorEl(event.currentTarget);
51
83
  };
84
+ const handleItemClick = (format, shape)=>()=>{
85
+ setAnchorEl(null);
86
+ let type, content = '';
87
+ switch(format){
88
+ case 'json':
89
+ type = 'application/json';
90
+ content = JSON.stringify(dashboard, null, 2);
91
+ break;
92
+ case 'yaml':
93
+ {
94
+ type = 'application/yaml';
95
+ if (shape === 'cr') {
96
+ const name = dashboard.metadata.name.toLowerCase().replace(/[^a-z0-9-]/g, '-');
97
+ content = (0, _yaml.stringify)({
98
+ apiVersion: 'perses.dev/v1alpha1',
99
+ kind: 'PersesDashboard',
100
+ metadata: {
101
+ labels: {
102
+ 'app.kubernetes.io/name': 'perses-dashboard',
103
+ 'app.kubernetes.io/instance': name,
104
+ 'app.kubernetes.io/part-of': 'perses-operator'
105
+ },
106
+ name
107
+ },
108
+ namespace: dashboard.metadata.project,
109
+ spec: dashboard.spec
110
+ });
111
+ } else {
112
+ content = (0, _yaml.stringify)(dashboard);
113
+ }
114
+ }
115
+ break;
116
+ }
117
+ if (!hiddenLinkRef || !hiddenLinkRef.current) return;
118
+ // Create blob URL
119
+ const hiddenLinkUrl = URL.createObjectURL(new Blob([
120
+ content
121
+ ], {
122
+ type
123
+ }));
124
+ // Simulate click
125
+ hiddenLinkRef.current.download = `${dashboard.metadata.name}${shape === 'cr' ? '-cr' : ''}.${format}`;
126
+ hiddenLinkRef.current.href = hiddenLinkUrl;
127
+ hiddenLinkRef.current.click();
128
+ // Remove blob URL (for memory management)
129
+ URL.revokeObjectURL(hiddenLinkUrl);
130
+ };
52
131
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_jsxruntime.Fragment, {
53
132
  children: [
54
- /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.InfoTooltip, {
55
- description: _constants.TOOLTIP_TEXT.downloadDashboard,
56
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ToolbarIconButton, {
57
- "aria-label": _constants.TOOLTIP_TEXT.downloadDashboard,
58
- onClick: onDownloadButtonClick,
59
- sx: {
60
- height
61
- },
62
- children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DownloadOutline.default, {})
133
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_components.ToolbarIconButton, {
134
+ id: "download-dashboard-button",
135
+ "aria-controls": open ? 'basic-menu' : undefined,
136
+ "aria-haspopup": "true",
137
+ "aria-expanded": open ? 'true' : undefined,
138
+ onClick: handleClick,
139
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_DownloadOutline.default, {})
140
+ }),
141
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Menu, {
142
+ id: "download-dashboard-formats",
143
+ anchorEl: anchorEl,
144
+ open: open,
145
+ hideBackdrop: true,
146
+ onClose: ()=>setAnchorEl(null),
147
+ MenuListProps: {
148
+ 'aria-labelledby': 'download-dashboard-button'
149
+ },
150
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)("div", {
151
+ children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.ClickAwayListener, {
152
+ onClickAway: ()=>setAnchorEl(null),
153
+ children: /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.MenuList, {
154
+ children: [
155
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
156
+ onClick: handleItemClick('json'),
157
+ children: "JSON"
158
+ }),
159
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
160
+ onClick: handleItemClick('yaml'),
161
+ children: "YAML"
162
+ }),
163
+ /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.MenuItem, {
164
+ onClick: handleItemClick('yaml', 'cr'),
165
+ children: "YAML (CR)"
166
+ })
167
+ ]
168
+ })
169
+ })
63
170
  })
64
171
  }),
65
172
  /*#__PURE__*/ (0, _jsxruntime.jsx)("a", {
66
173
  ref: hiddenLinkRef,
67
174
  style: {
68
175
  display: 'none'
69
- },
70
- download: `${dashboard.metadata.name}.json`
176
+ }
71
177
  })
72
178
  ]
73
179
  });
@@ -30,7 +30,7 @@ const EditJsonDialog = (props)=>{
30
30
  const { isReadonly, disableMetadataEdition } = props;
31
31
  const { editJsonDialog, closeEditJsonDialog } = (0, _context.useEditJsonDialog)();
32
32
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_components.Dialog, {
33
- open: !!(editJsonDialog === null || editJsonDialog === void 0 ? void 0 : editJsonDialog.isOpen),
33
+ open: !!editJsonDialog?.isOpen,
34
34
  scroll: "paper",
35
35
  fullWidth: true,
36
36
  maxWidth: "lg",
@@ -42,7 +42,7 @@ const EditJsonDialog = (props)=>{
42
42
  " Dashboard JSON"
43
43
  ]
44
44
  }),
45
- (editJsonDialog === null || editJsonDialog === void 0 ? void 0 : editJsonDialog.isOpen) && /*#__PURE__*/ (0, _jsxruntime.jsx)(EditJsonDialogForm, {
45
+ editJsonDialog?.isOpen && /*#__PURE__*/ (0, _jsxruntime.jsx)(EditJsonDialogForm, {
46
46
  isReadonly: isReadonly,
47
47
  disableMetadataEdition: disableMetadataEdition
48
48
  })
@@ -62,15 +62,13 @@ const EditJsonDialogForm = (props)=>{
62
62
  setTimeRange({
63
63
  pastDuration: draftDashboard.spec.duration
64
64
  });
65
- var _draftDashboard_spec_refreshInterval;
66
- setRefreshInterval((_draftDashboard_spec_refreshInterval = draftDashboard.spec.refreshInterval) !== null && _draftDashboard_spec_refreshInterval !== void 0 ? _draftDashboard_spec_refreshInterval : '0s');
67
- var _draftDashboard_spec_datasources;
68
- setLocalDatasources((_draftDashboard_spec_datasources = draftDashboard.spec.datasources) !== null && _draftDashboard_spec_datasources !== void 0 ? _draftDashboard_spec_datasources : {});
65
+ setRefreshInterval(draftDashboard.spec.refreshInterval ?? '0s');
66
+ setLocalDatasources(draftDashboard.spec.datasources ?? {});
69
67
  closeEditJsonDialog();
70
68
  };
71
69
  const completeDraftDashboard = (dashboard)=>{
72
70
  try {
73
- const json = JSON.parse(dashboard !== null && dashboard !== void 0 ? dashboard : '{}');
71
+ const json = JSON.parse(dashboard ?? '{}');
74
72
  setDraftDashboard(json);
75
73
  } catch (_) {
76
74
  // do nothing
@@ -105,7 +105,7 @@ const EmptyDashboard = ({ title = DEFAULT_TITLE, image, description, additionalT
105
105
  }),
106
106
  /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Typography, {
107
107
  variant: "body1",
108
- children: description !== null && description !== void 0 ? description : defaultDescription
108
+ children: description ?? defaultDescription
109
109
  }),
110
110
  actionsContent && /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
111
111
  sx: {
@@ -33,7 +33,7 @@ function GridItemContent(props) {
33
33
  const { spec: { queries } } = panelDefinition;
34
34
  const { isEditMode } = (0, _context.useEditMode)();
35
35
  const { openEditPanel, openDeletePanelDialog, duplicatePanel, viewPanel } = (0, _context.usePanelActions)(panelGroupItemId);
36
- const viewPanelGroupItemId = (0, _context.useViewPanel)();
36
+ const viewPanelGroupItemId = (0, _context.useViewPanelGroup)();
37
37
  const { ref, inView } = (0, _reactintersectionobserver.useInView)({
38
38
  threshold: 0.2,
39
39
  initialInView: false,
@@ -61,13 +61,14 @@ function GridItemContent(props) {
61
61
  // map TimeSeriesQueryDefinition to Definition<UnknownSpec>
62
62
  const suggestedStepMs = (0, _pluginsystem.useSuggestedStepMs)(width);
63
63
  const { data: plugin } = (0, _pluginsystem.usePlugin)('Panel', panelDefinition.spec.plugin.kind);
64
- const queryDefinitions = queries !== null && queries !== void 0 ? queries : [];
64
+ const queryDefinitions = queries ?? [];
65
65
  const definitions = queryDefinitions.map((query)=>{
66
66
  return {
67
67
  kind: query.spec.plugin.kind,
68
68
  spec: query.spec.plugin.spec
69
69
  };
70
70
  });
71
+ const pluginQueryOptions = typeof plugin?.queryOptions === 'function' ? plugin?.queryOptions(panelDefinition.spec.plugin.spec) : plugin?.queryOptions;
71
72
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
72
73
  ref: ref,
73
74
  sx: {
@@ -78,7 +79,7 @@ function GridItemContent(props) {
78
79
  definitions: definitions,
79
80
  options: {
80
81
  suggestedStepMs,
81
- ...plugin === null || plugin === void 0 ? void 0 : plugin.queryOptions
82
+ ...pluginQueryOptions
82
83
  },
83
84
  queryOptions: {
84
85
  enabled: inView
@@ -37,13 +37,12 @@ function GridLayout(props) {
37
37
  const theme = (0, _material.useTheme)();
38
38
  const groupDefinition = (0, _context.usePanelGroup)(panelGroupId);
39
39
  const { updatePanelGroupLayouts } = (0, _context.usePanelGroupActions)(panelGroupId);
40
- var _ref;
41
- const [isOpen, setIsOpen] = (0, _react.useState)((_ref = !groupDefinition.isCollapsed) !== null && _ref !== void 0 ? _ref : true);
40
+ const [isOpen, setIsOpen] = (0, _react.useState)(!groupDefinition.isCollapsed);
42
41
  const { isEditMode } = (0, _context.useEditMode)();
43
42
  const [gridColWidth, setGridColWidth] = (0, _react.useState)(0);
44
- const viewPanelItemId = (0, _context.useViewPanel)();
45
- const hasViewPanel = (viewPanelItemId === null || viewPanelItemId === void 0 ? void 0 : viewPanelItemId.panelGroupId) === panelGroupId; // current panelGroup contains the panel extended?
46
- const itemLayoutViewed = viewPanelItemId === null || viewPanelItemId === void 0 ? void 0 : viewPanelItemId.panelGroupItemLayoutId;
43
+ const viewPanelItemId = (0, _context.useViewPanelGroup)();
44
+ const hasViewPanel = viewPanelItemId?.panelGroupId === panelGroupId; // current panelGroup contains the panel extended?
45
+ const itemLayoutViewed = viewPanelItemId?.panelGroupItemLayoutId;
47
46
  // If there is a panel in view mode, we should hide the grid if the panel is not in the current group.
48
47
  const isGridDisplayed = (0, _react.useMemo)(()=>{
49
48
  if (viewPanelItemId === undefined) {
@@ -64,7 +63,7 @@ function GridLayout(props) {
64
63
  if (itemLayout.i === itemLayoutViewed) {
65
64
  const rowTitleHeight = 40 + 8; // 40 is the height of the row title and 8 is the margin height
66
65
  return {
67
- h: Math.round(((panelFullHeight !== null && panelFullHeight !== void 0 ? panelFullHeight : window.innerHeight) - rowTitleHeight) / (ROW_HEIGHT + DEFAULT_MARGIN)),
66
+ h: Math.round(((panelFullHeight ?? window.innerHeight) - rowTitleHeight) / (ROW_HEIGHT + DEFAULT_MARGIN)),
68
67
  i: itemLayoutViewed,
69
68
  w: 48,
70
69
  x: 0,
@@ -49,7 +49,7 @@ function GridTitle(props) {
49
49
  children: title
50
50
  });
51
51
  return /*#__PURE__*/ (0, _jsxruntime.jsx)(_material.Box, {
52
- onClick: collapse === null || collapse === void 0 ? void 0 : collapse.onToggleOpen,
52
+ onClick: collapse?.onToggleOpen,
53
53
  sx: {
54
54
  display: 'flex',
55
55
  justifyContent: 'start',
@@ -116,7 +116,7 @@ function GridTitle(props) {
116
116
  onClick: (e)=>{
117
117
  // Don't trigger expand/collapse
118
118
  e.stopPropagation();
119
- moveDown === null || moveDown === void 0 ? void 0 : moveDown();
119
+ moveDown?.();
120
120
  },
121
121
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ArrowDown.default, {})
122
122
  })
@@ -129,7 +129,7 @@ function GridTitle(props) {
129
129
  onClick: (e)=>{
130
130
  // Don't trigger expand/collapse
131
131
  e.stopPropagation();
132
- moveUp === null || moveUp === void 0 ? void 0 : moveUp();
132
+ moveUp?.();
133
133
  },
134
134
  children: /*#__PURE__*/ (0, _jsxruntime.jsx)(_ArrowUp.default, {})
135
135
  })
@@ -0,0 +1,27 @@
1
+ // Copyright 2025 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, "HeaderIconButton", {
18
+ enumerable: true,
19
+ get: function() {
20
+ return HeaderIconButton;
21
+ }
22
+ });
23
+ const _material = require("@mui/material");
24
+ const HeaderIconButton = (0, _material.styled)(_material.IconButton)(({ theme })=>({
25
+ borderRadius: theme.shape.borderRadius,
26
+ padding: '4px'
27
+ }));
@@ -21,19 +21,19 @@ Object.defineProperty(exports, "Panel", {
21
21
  }
22
22
  });
23
23
  const _jsxruntime = require("react/jsx-runtime");
24
+ const _material = require("@mui/material");
25
+ const _components = require("@perses-dev/components");
26
+ const _pluginsystem = require("@perses-dev/plugin-system");
24
27
  const _react = require("react");
25
28
  const _useresizeobserver = /*#__PURE__*/ _interop_require_default(require("use-resize-observer"));
26
- const _components = require("@perses-dev/components");
27
- const _material = require("@mui/material");
28
- const _PanelHeader = require("./PanelHeader");
29
29
  const _PanelContent = require("./PanelContent");
30
+ const _PanelHeader = require("./PanelHeader");
30
31
  function _interop_require_default(obj) {
31
32
  return obj && obj.__esModule ? obj : {
32
33
  default: obj
33
34
  };
34
35
  }
35
36
  const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
36
- var _panelOptions_extra;
37
37
  const { definition, readHandlers, editHandlers, onMouseEnter, onMouseLeave, sx, panelOptions, panelGroupItemId, ...others } = props;
38
38
  // Make sure we have an ID we can use for aria attributes
39
39
  const generatedPanelId = (0, _components.useId)('Panel');
@@ -53,11 +53,12 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
53
53
  height
54
54
  ]);
55
55
  const chartsTheme = (0, _components.useChartsTheme)();
56
+ const { queryResults } = (0, _pluginsystem.useDataQueriesContext)();
56
57
  const handleMouseEnter = (e)=>{
57
- onMouseEnter === null || onMouseEnter === void 0 ? void 0 : onMouseEnter(e);
58
+ onMouseEnter?.(e);
58
59
  };
59
60
  const handleMouseLeave = (e)=>{
60
- onMouseLeave === null || onMouseLeave === void 0 ? void 0 : onMouseLeave(e);
61
+ onMouseLeave?.(e);
61
62
  };
62
63
  return /*#__PURE__*/ (0, _jsxruntime.jsxs)(_material.Card, {
63
64
  component: "section",
@@ -65,7 +66,10 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
65
66
  width: '100%',
66
67
  height: '100%',
67
68
  display: 'flex',
68
- flexFlow: 'column nowrap'
69
+ flexFlow: 'column nowrap',
70
+ ':hover': {
71
+ '--panel-hover': 'block'
72
+ }
69
73
  }, sx),
70
74
  variant: "outlined",
71
75
  onMouseEnter: handleMouseEnter,
@@ -75,14 +79,15 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
75
79
  "data-testid": "panel",
76
80
  ...others,
77
81
  children: [
78
- !(panelOptions === null || panelOptions === void 0 ? void 0 : panelOptions.hideHeader) && /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelHeader.PanelHeader, {
79
- extra: panelOptions === null || panelOptions === void 0 ? void 0 : (_panelOptions_extra = panelOptions.extra) === null || _panelOptions_extra === void 0 ? void 0 : _panelOptions_extra.call(panelOptions, {
82
+ !panelOptions?.hideHeader && /*#__PURE__*/ (0, _jsxruntime.jsx)(_PanelHeader.PanelHeader, {
83
+ extra: panelOptions?.extra?.({
80
84
  panelDefinition: definition,
81
85
  panelGroupItemId
82
86
  }),
83
87
  id: headerId,
84
88
  title: definition.spec.display.name,
85
89
  description: definition.spec.display.description,
90
+ queryResults: queryResults,
86
91
  readHandlers: readHandlers,
87
92
  editHandlers: editHandlers,
88
93
  links: definition.spec.links,
@@ -113,7 +118,8 @@ const Panel = /*#__PURE__*/ (0, _react.memo)(function Panel(props) {
113
118
  definition: definition,
114
119
  panelPluginKind: definition.spec.plugin.kind,
115
120
  spec: definition.spec.plugin.spec,
116
- contentDimensions: contentDimensions
121
+ contentDimensions: contentDimensions,
122
+ queryResults: queryResults
117
123
  })
118
124
  })
119
125
  })