@backstage/plugin-home 0.7.3-next.1 → 0.7.4-next.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 (142) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/alpha/package.json +1 -1
  3. package/dist/alpha.esm.js +1 -1
  4. package/dist/alpha.esm.js.map +1 -1
  5. package/dist/api/VisitsApi.esm.js +11 -0
  6. package/dist/api/VisitsApi.esm.js.map +1 -0
  7. package/dist/api/VisitsStorageApi.esm.js +118 -0
  8. package/dist/api/VisitsStorageApi.esm.js.map +1 -0
  9. package/dist/api/VisitsWebStorageApi.esm.js +15 -0
  10. package/dist/api/VisitsWebStorageApi.esm.js.map +1 -0
  11. package/dist/api/config.esm.js +37 -0
  12. package/dist/api/config.esm.js.map +1 -0
  13. package/dist/assets/TemplateBackstageLogo.esm.js +22 -0
  14. package/dist/assets/TemplateBackstageLogo.esm.js.map +1 -0
  15. package/dist/assets/TemplateBackstageLogoIcon.esm.js +33 -0
  16. package/dist/assets/TemplateBackstageLogoIcon.esm.js.map +1 -0
  17. package/dist/{esm/index-BNfZuEhy.esm.js → componentRenderers/ComponentAccordion.esm.js} +2 -26
  18. package/dist/componentRenderers/ComponentAccordion.esm.js.map +1 -0
  19. package/dist/componentRenderers/ComponentTabs/ComponentTab.esm.js +9 -0
  20. package/dist/componentRenderers/ComponentTabs/ComponentTab.esm.js.map +1 -0
  21. package/dist/componentRenderers/ComponentTabs/ComponentTabs.esm.js +23 -0
  22. package/dist/componentRenderers/ComponentTabs/ComponentTabs.esm.js.map +1 -0
  23. package/dist/componentRenderers/index.esm.js +4 -0
  24. package/dist/componentRenderers/index.esm.js.map +1 -0
  25. package/dist/components/CustomHomepage/AddWidgetDialog.esm.js +45 -0
  26. package/dist/components/CustomHomepage/AddWidgetDialog.esm.js.map +1 -0
  27. package/dist/components/CustomHomepage/CustomHomepageButtons.esm.js +90 -0
  28. package/dist/components/CustomHomepage/CustomHomepageButtons.esm.js.map +1 -0
  29. package/dist/components/CustomHomepage/CustomHomepageGrid.esm.js +319 -0
  30. package/dist/components/CustomHomepage/CustomHomepageGrid.esm.js.map +1 -0
  31. package/dist/components/CustomHomepage/WidgetSettingsOverlay.esm.js +88 -0
  32. package/dist/components/CustomHomepage/WidgetSettingsOverlay.esm.js.map +1 -0
  33. package/dist/components/CustomHomepage/types.esm.js +48 -0
  34. package/dist/components/CustomHomepage/types.esm.js.map +1 -0
  35. package/dist/components/HomepageCompositionRoot.esm.js +12 -0
  36. package/dist/components/HomepageCompositionRoot.esm.js.map +1 -0
  37. package/dist/components/StarredEntityListItem/StarredEntityListItem.esm.js +31 -0
  38. package/dist/components/StarredEntityListItem/StarredEntityListItem.esm.js.map +1 -0
  39. package/dist/components/VisitList/ItemCategory.esm.js +63 -0
  40. package/dist/components/VisitList/ItemCategory.esm.js.map +1 -0
  41. package/dist/components/VisitList/ItemDetail.esm.js +26 -0
  42. package/dist/components/VisitList/ItemDetail.esm.js.map +1 -0
  43. package/dist/components/VisitList/ItemName.esm.js +27 -0
  44. package/dist/components/VisitList/ItemName.esm.js.map +1 -0
  45. package/dist/components/VisitList/VisitList.esm.js +46 -0
  46. package/dist/components/VisitList/VisitList.esm.js.map +1 -0
  47. package/dist/components/VisitList/VisitListEmpty.esm.js +7 -0
  48. package/dist/components/VisitList/VisitListEmpty.esm.js.map +1 -0
  49. package/dist/components/VisitList/VisitListFew.esm.js +7 -0
  50. package/dist/components/VisitList/VisitListFew.esm.js.map +1 -0
  51. package/dist/components/VisitList/VisitListItem.esm.js +31 -0
  52. package/dist/components/VisitList/VisitListItem.esm.js.map +1 -0
  53. package/dist/components/VisitList/VisitListSkeleton.esm.js +39 -0
  54. package/dist/components/VisitList/VisitListSkeleton.esm.js.map +1 -0
  55. package/dist/components/VisitListener.esm.js +62 -0
  56. package/dist/components/VisitListener.esm.js.map +1 -0
  57. package/dist/components/index.esm.js +4 -0
  58. package/dist/components/index.esm.js.map +1 -0
  59. package/dist/deprecated.esm.js +7 -0
  60. package/dist/deprecated.esm.js.map +1 -0
  61. package/dist/{esm/index-FqRX6ImF.esm.js → homePageComponents/CompanyLogo/CompanyLogo.esm.js} +1 -1
  62. package/dist/{esm/index-FqRX6ImF.esm.js.map → homePageComponents/CompanyLogo/CompanyLogo.esm.js.map} +1 -1
  63. package/dist/homePageComponents/CompanyLogo/index.esm.js +2 -0
  64. package/dist/homePageComponents/CompanyLogo/index.esm.js.map +1 -0
  65. package/dist/{esm/index-D7JTE1IL.esm.js → homePageComponents/FeaturedDocsCard/Content.esm.js} +1 -1
  66. package/dist/homePageComponents/FeaturedDocsCard/Content.esm.js.map +1 -0
  67. package/dist/homePageComponents/FeaturedDocsCard/index.esm.js +2 -0
  68. package/dist/homePageComponents/FeaturedDocsCard/index.esm.js.map +1 -0
  69. package/dist/{esm/index-BvvJGS3L.esm.js → homePageComponents/HeaderWorldClock/HeaderWorldClock.esm.js} +1 -1
  70. package/dist/homePageComponents/HeaderWorldClock/HeaderWorldClock.esm.js.map +1 -0
  71. package/dist/homePageComponents/HeaderWorldClock/index.esm.js +2 -0
  72. package/dist/homePageComponents/HeaderWorldClock/index.esm.js.map +1 -0
  73. package/dist/homePageComponents/RandomJoke/Actions.esm.js +11 -0
  74. package/dist/homePageComponents/RandomJoke/Actions.esm.js.map +1 -0
  75. package/dist/homePageComponents/RandomJoke/Content.esm.js +13 -0
  76. package/dist/homePageComponents/RandomJoke/Content.esm.js.map +1 -0
  77. package/dist/homePageComponents/RandomJoke/Context.esm.js +48 -0
  78. package/dist/homePageComponents/RandomJoke/Context.esm.js.map +1 -0
  79. package/dist/homePageComponents/RandomJoke/Settings.esm.js +33 -0
  80. package/dist/homePageComponents/RandomJoke/Settings.esm.js.map +1 -0
  81. package/dist/homePageComponents/RandomJoke/index.esm.js +5 -0
  82. package/dist/homePageComponents/RandomJoke/index.esm.js.map +1 -0
  83. package/dist/{esm/index-SfHoDIi1.esm.js → homePageComponents/StarredEntities/Content.esm.js} +4 -27
  84. package/dist/homePageComponents/StarredEntities/Content.esm.js.map +1 -0
  85. package/dist/homePageComponents/StarredEntities/index.esm.js +2 -0
  86. package/dist/homePageComponents/StarredEntities/index.esm.js.map +1 -0
  87. package/dist/{esm/index-CeXFfTX2.esm.js → homePageComponents/Toolkit/Content.esm.js} +4 -17
  88. package/dist/homePageComponents/Toolkit/Content.esm.js.map +1 -0
  89. package/dist/homePageComponents/Toolkit/Context.esm.js +18 -0
  90. package/dist/homePageComponents/Toolkit/Context.esm.js.map +1 -0
  91. package/dist/homePageComponents/Toolkit/index.esm.js +3 -0
  92. package/dist/homePageComponents/Toolkit/index.esm.js.map +1 -0
  93. package/dist/homePageComponents/VisitedByType/Actions.esm.js +18 -0
  94. package/dist/homePageComponents/VisitedByType/Actions.esm.js.map +1 -0
  95. package/dist/homePageComponents/VisitedByType/Content.esm.js +68 -0
  96. package/dist/homePageComponents/VisitedByType/Content.esm.js.map +1 -0
  97. package/dist/homePageComponents/VisitedByType/Context.esm.js +77 -0
  98. package/dist/homePageComponents/VisitedByType/Context.esm.js.map +1 -0
  99. package/dist/homePageComponents/VisitedByType/RecentlyVisited.esm.js +9 -0
  100. package/dist/homePageComponents/VisitedByType/RecentlyVisited.esm.js.map +1 -0
  101. package/dist/homePageComponents/VisitedByType/TopVisited.esm.js +9 -0
  102. package/dist/homePageComponents/VisitedByType/TopVisited.esm.js.map +1 -0
  103. package/dist/homePageComponents/VisitedByType/VisitedByType.esm.js +21 -0
  104. package/dist/homePageComponents/VisitedByType/VisitedByType.esm.js.map +1 -0
  105. package/dist/homePageComponents/WelcomeTitle/WelcomeTitle.esm.js +27 -0
  106. package/dist/homePageComponents/WelcomeTitle/WelcomeTitle.esm.js.map +1 -0
  107. package/dist/homePageComponents/WelcomeTitle/index.esm.js +2 -0
  108. package/dist/homePageComponents/WelcomeTitle/index.esm.js.map +1 -0
  109. package/dist/homePageComponents/WelcomeTitle/locales/goodAfternoon.locales.json.esm.js +256 -0
  110. package/dist/homePageComponents/WelcomeTitle/locales/goodAfternoon.locales.json.esm.js.map +1 -0
  111. package/dist/homePageComponents/WelcomeTitle/locales/goodEvening.locales.json.esm.js +196 -0
  112. package/dist/homePageComponents/WelcomeTitle/locales/goodEvening.locales.json.esm.js.map +1 -0
  113. package/dist/homePageComponents/WelcomeTitle/locales/goodMorning.locales.json.esm.js +131 -0
  114. package/dist/homePageComponents/WelcomeTitle/locales/goodMorning.locales.json.esm.js.map +1 -0
  115. package/dist/homePageComponents/WelcomeTitle/timeUtil.esm.js +41 -0
  116. package/dist/homePageComponents/WelcomeTitle/timeUtil.esm.js.map +1 -0
  117. package/dist/index.esm.js +10 -352
  118. package/dist/index.esm.js.map +1 -1
  119. package/dist/plugin.esm.js +144 -0
  120. package/dist/plugin.esm.js.map +1 -0
  121. package/dist/routes.esm.js +8 -0
  122. package/dist/routes.esm.js.map +1 -0
  123. package/package.json +20 -20
  124. package/dist/esm/Content-Quo42yad.esm.js +0 -396
  125. package/dist/esm/Content-Quo42yad.esm.js.map +0 -1
  126. package/dist/esm/RecentlyVisited-qOUgoCVu.esm.js +0 -48
  127. package/dist/esm/RecentlyVisited-qOUgoCVu.esm.js.map +0 -1
  128. package/dist/esm/TopVisited-B_KhSJit.esm.js +0 -48
  129. package/dist/esm/TopVisited-B_KhSJit.esm.js.map +0 -1
  130. package/dist/esm/VisitListener-dDLtFiIW.esm.js +0 -627
  131. package/dist/esm/VisitListener-dDLtFiIW.esm.js.map +0 -1
  132. package/dist/esm/index-BMySa_Iw.esm.js +0 -638
  133. package/dist/esm/index-BMySa_Iw.esm.js.map +0 -1
  134. package/dist/esm/index-BNfZuEhy.esm.js.map +0 -1
  135. package/dist/esm/index-BvvJGS3L.esm.js.map +0 -1
  136. package/dist/esm/index-Bzg5mDMo.esm.js +0 -45
  137. package/dist/esm/index-Bzg5mDMo.esm.js.map +0 -1
  138. package/dist/esm/index-CeXFfTX2.esm.js.map +0 -1
  139. package/dist/esm/index-D7JTE1IL.esm.js.map +0 -1
  140. package/dist/esm/index-Dg9lslkf.esm.js +0 -90
  141. package/dist/esm/index-Dg9lslkf.esm.js.map +0 -1
  142. package/dist/esm/index-SfHoDIi1.esm.js.map +0 -1
@@ -1,48 +0,0 @@
1
- import { C as Content } from './Content-Quo42yad.esm.js';
2
- export { A as Actions, a as ContextProvider } from './Content-Quo42yad.esm.js';
3
- import React from 'react';
4
- import '@material-ui/core/Button';
5
- import './VisitListener-dDLtFiIW.esm.js';
6
- import 'react-grid-layout';
7
- import '@backstage/core-plugin-api';
8
- import 'react-grid-layout/css/styles.css';
9
- import 'react-resizable/css/styles.css';
10
- import '@material-ui/core/Dialog';
11
- import '@material-ui/core/styles';
12
- import 'lodash';
13
- import 'react-use/esm/useObservable';
14
- import '@backstage/core-components';
15
- import '@material-ui/core/Typography';
16
- import '@material-ui/core/DialogContent';
17
- import '@material-ui/core/Grid';
18
- import '@material-ui/core/Tooltip';
19
- import '@material-ui/core/IconButton';
20
- import '@material-ui/icons/Settings';
21
- import '@material-ui/icons/Delete';
22
- import '@rjsf/core';
23
- import '@rjsf/material-ui';
24
- import '@rjsf/validator-ajv8';
25
- import '@material-ui/core/List';
26
- import '@material-ui/core/ListItem';
27
- import '@material-ui/core/DialogTitle';
28
- import '@material-ui/core/ListItemAvatar';
29
- import '@material-ui/icons/Add';
30
- import '@material-ui/core/ListItemText';
31
- import '@material-ui/icons/Save';
32
- import '@material-ui/icons/Edit';
33
- import '@material-ui/icons/Cancel';
34
- import 'zod';
35
- import 'react-router-dom';
36
- import '@backstage/core-app-api';
37
- import '@backstage/catalog-model';
38
- import '@material-ui/core/Collapse';
39
- import 'luxon';
40
- import '@material-ui/core/Chip';
41
- import '@backstage/theme';
42
- import '@material-ui/lab/Skeleton';
43
- import 'react-use/esm/useAsync';
44
-
45
- const TopVisitedContent = (props) => /* @__PURE__ */ React.createElement(Content, { ...props, kind: "top" });
46
-
47
- export { TopVisitedContent as Content };
48
- //# sourceMappingURL=TopVisited-B_KhSJit.esm.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"TopVisited-B_KhSJit.esm.js","sources":["../../src/homePageComponents/VisitedByType/TopVisited.tsx"],"sourcesContent":["/*\n * Copyright 2023 The Backstage Authors\n *\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 */\n\nexport { Actions } from './Actions';\nexport { ContextProvider } from './Context';\nexport type { VisitedByTypeProps, VisitedByTypeKind } from './Content';\nimport React from 'react';\nimport { Content, VisitedByTypeProps } from './Content';\n\nconst TopVisitedContent = (props: Partial<VisitedByTypeProps>) => (\n <Content {...props} kind=\"top\" />\n);\n\nexport { TopVisitedContent as Content };\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsBM,MAAA,iBAAA,GAAoB,CAAC,KACzB,qBAAA,KAAA,CAAA,aAAA,CAAC,WAAS,GAAG,KAAA,EAAO,MAAK,KAAM,EAAA;;;;"}
@@ -1,627 +0,0 @@
1
- import React, { useMemo, useCallback, useEffect } from 'react';
2
- import { WidthProvider, Responsive } from 'react-grid-layout';
3
- import { createApiRef, useElementFilter, useApi, storageApiRef, getComponentData } from '@backstage/core-plugin-api';
4
- import 'react-grid-layout/css/styles.css';
5
- import 'react-resizable/css/styles.css';
6
- import Dialog from '@material-ui/core/Dialog';
7
- import { makeStyles, createStyles, useTheme } from '@material-ui/core/styles';
8
- import { compact } from 'lodash';
9
- import useObservable from 'react-use/esm/useObservable';
10
- import { ContentHeader, ErrorBoundary } from '@backstage/core-components';
11
- import Typography from '@material-ui/core/Typography';
12
- import DialogContent from '@material-ui/core/DialogContent';
13
- import Grid from '@material-ui/core/Grid';
14
- import Tooltip from '@material-ui/core/Tooltip';
15
- import IconButton from '@material-ui/core/IconButton';
16
- import SettingsIcon from '@material-ui/icons/Settings';
17
- import DeleteIcon from '@material-ui/icons/Delete';
18
- import { withTheme } from '@rjsf/core';
19
- import { Theme } from '@rjsf/material-ui';
20
- import validator from '@rjsf/validator-ajv8';
21
- import List from '@material-ui/core/List';
22
- import ListItem from '@material-ui/core/ListItem';
23
- import DialogTitle from '@material-ui/core/DialogTitle';
24
- import ListItemAvatar from '@material-ui/core/ListItemAvatar';
25
- import AddIcon from '@material-ui/icons/Add';
26
- import ListItemText from '@material-ui/core/ListItemText';
27
- import Button from '@material-ui/core/Button';
28
- import SaveIcon from '@material-ui/icons/Save';
29
- import EditIcon from '@material-ui/icons/Edit';
30
- import CancelIcon from '@material-ui/icons/Cancel';
31
- import { z } from 'zod';
32
- import { useLocation } from 'react-router-dom';
33
- import '@backstage/core-app-api';
34
- import { stringifyEntityRef } from '@backstage/catalog-model';
35
-
36
- const isOperator = (s) => {
37
- return ["<", "<=", "==", "!=", ">", ">=", "contains"].includes(s);
38
- };
39
- const visitsApiRef = createApiRef({
40
- id: "homepage.visits"
41
- });
42
-
43
- const Form = withTheme(Theme);
44
- const useStyles$2 = makeStyles(
45
- (theme) => createStyles({
46
- iconGrid: {
47
- height: "100%",
48
- "& *": {
49
- padding: 0
50
- }
51
- },
52
- settingsOverlay: {
53
- position: "absolute",
54
- backgroundColor: "rgba(40, 40, 40, 0.93)",
55
- width: "100%",
56
- height: "100%",
57
- top: 0,
58
- left: 0,
59
- padding: theme.spacing(2),
60
- color: "white"
61
- }
62
- })
63
- );
64
- const WidgetSettingsOverlay = (props) => {
65
- const { id, widget, settings, handleRemove, handleSettingsSave, deletable } = props;
66
- const [settingsDialogOpen, setSettingsDialogOpen] = React.useState(false);
67
- const styles = useStyles$2();
68
- return /* @__PURE__ */ React.createElement("div", { className: styles.settingsOverlay }, widget.settingsSchema && /* @__PURE__ */ React.createElement(
69
- Dialog,
70
- {
71
- open: settingsDialogOpen,
72
- className: "widgetSettingsDialog",
73
- onClose: () => setSettingsDialogOpen(false)
74
- },
75
- /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(
76
- Form,
77
- {
78
- validator,
79
- showErrorList: false,
80
- schema: widget.settingsSchema,
81
- uiSchema: widget.uiSchema,
82
- noHtml5Validate: true,
83
- formData: settings,
84
- formContext: { settings },
85
- onSubmit: ({ formData, errors }) => {
86
- if (errors.length === 0) {
87
- handleSettingsSave(id, formData);
88
- setSettingsDialogOpen(false);
89
- }
90
- },
91
- experimental_defaultFormStateBehavior: {
92
- allOf: "populateDefaults"
93
- }
94
- }
95
- ))
96
- ), /* @__PURE__ */ React.createElement(
97
- Grid,
98
- {
99
- container: true,
100
- className: styles.iconGrid,
101
- alignItems: "center",
102
- justifyContent: "center"
103
- },
104
- widget.settingsSchema && /* @__PURE__ */ React.createElement(Grid, { item: true, className: "overlayGridItem" }, /* @__PURE__ */ React.createElement(Tooltip, { title: "Edit settings" }, /* @__PURE__ */ React.createElement(
105
- IconButton,
106
- {
107
- color: "primary",
108
- onClick: () => setSettingsDialogOpen(true)
109
- },
110
- /* @__PURE__ */ React.createElement(SettingsIcon, { fontSize: "large" })
111
- ))),
112
- deletable !== false && /* @__PURE__ */ React.createElement(Grid, { item: true, className: "overlayGridItem" }, /* @__PURE__ */ React.createElement(Tooltip, { title: "Delete widget" }, /* @__PURE__ */ React.createElement(IconButton, { color: "secondary", onClick: () => handleRemove(id) }, /* @__PURE__ */ React.createElement(DeleteIcon, { fontSize: "large" }))))
113
- ));
114
- };
115
-
116
- const getTitle = (widget) => {
117
- return widget.title || widget.name;
118
- };
119
- const AddWidgetDialog = (props) => {
120
- const { widgets, handleAdd } = props;
121
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(DialogTitle, null, "Add new widget to dashboard"), /* @__PURE__ */ React.createElement(DialogContent, null, /* @__PURE__ */ React.createElement(List, { dense: true }, widgets.map((widget) => {
122
- return /* @__PURE__ */ React.createElement(
123
- ListItem,
124
- {
125
- key: widget.name,
126
- button: true,
127
- onClick: () => handleAdd(widget)
128
- },
129
- /* @__PURE__ */ React.createElement(ListItemAvatar, null, /* @__PURE__ */ React.createElement(AddIcon, null)),
130
- /* @__PURE__ */ React.createElement(
131
- ListItemText,
132
- {
133
- secondary: widget.description && /* @__PURE__ */ React.createElement(
134
- Typography,
135
- {
136
- component: "span",
137
- variant: "caption",
138
- color: "textPrimary"
139
- },
140
- widget.description
141
- ),
142
- primary: /* @__PURE__ */ React.createElement(Typography, { variant: "body1", color: "textPrimary" }, getTitle(widget))
143
- }
144
- )
145
- );
146
- }))));
147
- };
148
-
149
- const useStyles$1 = makeStyles(
150
- (theme) => createStyles({
151
- contentHeaderBtn: {
152
- marginLeft: theme.spacing(2)
153
- },
154
- widgetWrapper: {
155
- "& > *:first-child": {
156
- width: "100%",
157
- height: "100%"
158
- }
159
- }
160
- })
161
- );
162
- const CustomHomepageButtons = (props) => {
163
- const {
164
- editMode,
165
- numWidgets,
166
- clearLayout,
167
- setAddWidgetDialogOpen,
168
- changeEditMode,
169
- defaultConfigAvailable,
170
- restoreDefault
171
- } = props;
172
- const styles = useStyles$1();
173
- return /* @__PURE__ */ React.createElement(React.Fragment, null, !editMode && numWidgets > 0 ? /* @__PURE__ */ React.createElement(
174
- Button,
175
- {
176
- variant: "contained",
177
- color: "primary",
178
- onClick: () => changeEditMode(true),
179
- size: "small",
180
- startIcon: /* @__PURE__ */ React.createElement(EditIcon, null)
181
- },
182
- "Edit"
183
- ) : /* @__PURE__ */ React.createElement(React.Fragment, null, defaultConfigAvailable && /* @__PURE__ */ React.createElement(
184
- Button,
185
- {
186
- variant: "contained",
187
- className: styles.contentHeaderBtn,
188
- onClick: restoreDefault,
189
- size: "small",
190
- startIcon: /* @__PURE__ */ React.createElement(CancelIcon, null)
191
- },
192
- "Restore defaults"
193
- ), numWidgets > 0 && /* @__PURE__ */ React.createElement(
194
- Button,
195
- {
196
- variant: "contained",
197
- color: "secondary",
198
- className: styles.contentHeaderBtn,
199
- onClick: clearLayout,
200
- size: "small",
201
- startIcon: /* @__PURE__ */ React.createElement(DeleteIcon, null)
202
- },
203
- "Clear all"
204
- ), /* @__PURE__ */ React.createElement(
205
- Button,
206
- {
207
- variant: "contained",
208
- className: styles.contentHeaderBtn,
209
- onClick: () => setAddWidgetDialogOpen(true),
210
- size: "small",
211
- startIcon: /* @__PURE__ */ React.createElement(AddIcon, null)
212
- },
213
- "Add widget"
214
- ), numWidgets > 0 && /* @__PURE__ */ React.createElement(
215
- Button,
216
- {
217
- className: styles.contentHeaderBtn,
218
- variant: "contained",
219
- color: "primary",
220
- onClick: () => changeEditMode(false),
221
- size: "small",
222
- startIcon: /* @__PURE__ */ React.createElement(SaveIcon, null)
223
- },
224
- "Save"
225
- )));
226
- };
227
-
228
- const RSJFTypeSchema = z.any();
229
- const RSJFTypeUiSchema = z.any();
230
- const ReactElementSchema = z.any();
231
- const LayoutSchema = z.any();
232
- const LayoutConfigurationSchema = z.object({
233
- component: ReactElementSchema,
234
- x: z.number().nonnegative("x must be positive number"),
235
- y: z.number().nonnegative("y must be positive number"),
236
- width: z.number().positive("width must be positive number"),
237
- height: z.number().positive("height must be positive number"),
238
- movable: z.boolean().optional(),
239
- deletable: z.boolean().optional(),
240
- resizable: z.boolean().optional()
241
- });
242
- const WidgetSchema = z.object({
243
- name: z.string(),
244
- title: z.string().optional(),
245
- description: z.string().optional(),
246
- component: ReactElementSchema,
247
- width: z.number().positive("width must be positive number").optional(),
248
- height: z.number().positive("height must be positive number").optional(),
249
- minWidth: z.number().positive("minWidth must be positive number").optional(),
250
- maxWidth: z.number().positive("maxWidth must be positive number").optional(),
251
- minHeight: z.number().positive("minHeight must be positive number").optional(),
252
- maxHeight: z.number().positive("maxHeight must be positive number").optional(),
253
- settingsSchema: RSJFTypeSchema.optional(),
254
- uiSchema: RSJFTypeUiSchema.optional(),
255
- movable: z.boolean().optional(),
256
- deletable: z.boolean().optional(),
257
- resizable: z.boolean().optional()
258
- });
259
- const GridWidgetSchema = z.object({
260
- id: z.string(),
261
- layout: LayoutSchema,
262
- settings: z.record(z.string(), z.any()),
263
- movable: z.boolean().optional(),
264
- deletable: z.boolean().optional(),
265
- resizable: z.boolean().optional()
266
- });
267
- const CustomHomepageGridStateV1Schema = z.object({
268
- version: z.literal(1),
269
- pages: z.record(z.string(), z.array(GridWidgetSchema))
270
- });
271
-
272
- const ResponsiveGrid = WidthProvider(Responsive);
273
- const useStyles = makeStyles(
274
- (theme) => createStyles({
275
- responsiveGrid: {
276
- "& .react-grid-item > .react-resizable-handle:after": {
277
- position: "absolute",
278
- content: '""',
279
- borderStyle: "solid",
280
- borderWidth: "0 0 20px 20px",
281
- borderColor: `transparent transparent ${theme.palette.primary.light} transparent`
282
- }
283
- },
284
- contentHeaderBtn: {
285
- marginLeft: theme.spacing(2)
286
- },
287
- widgetWrapper: {
288
- '& > div[class*="MuiCard-root"]': {
289
- width: "100%",
290
- height: "100%"
291
- },
292
- '& div[class*="MuiCardContent-root"]': {
293
- overflow: "auto"
294
- },
295
- "& + .react-grid-placeholder": {
296
- backgroundColor: theme.palette.primary.light
297
- },
298
- "&.edit > :active": {
299
- cursor: "move"
300
- }
301
- }
302
- })
303
- );
304
- function useHomeStorage(defaultWidgets) {
305
- const key = "home";
306
- const storageApi = useApi(storageApiRef).forBucket("home.customHomepage");
307
- const setWidgets = useCallback(
308
- (value) => {
309
- const grid = {
310
- version: 1,
311
- pages: {
312
- default: value
313
- }
314
- };
315
- storageApi.set(key, JSON.stringify(grid));
316
- },
317
- [key, storageApi]
318
- );
319
- const homeSnapshot = useObservable(
320
- storageApi.observe$(key),
321
- storageApi.snapshot(key)
322
- );
323
- const widgets = useMemo(() => {
324
- if (homeSnapshot.presence === "absent") {
325
- return defaultWidgets;
326
- }
327
- try {
328
- const grid = JSON.parse(homeSnapshot.value);
329
- return CustomHomepageGridStateV1Schema.parse(grid).pages.default;
330
- } catch (e) {
331
- return defaultWidgets;
332
- }
333
- }, [homeSnapshot, defaultWidgets]);
334
- return [widgets, setWidgets];
335
- }
336
- const convertConfigToDefaultWidgets = (config, availableWidgets) => {
337
- const ret = config.map((conf, i) => {
338
- var _a, _b;
339
- const c = LayoutConfigurationSchema.parse(conf);
340
- const name = React.isValidElement(c.component) ? getComponentData(c.component, "core.extensionName") : c.component;
341
- if (!name) {
342
- return null;
343
- }
344
- const widget = availableWidgets.find((w) => w.name === name);
345
- if (!widget) {
346
- return null;
347
- }
348
- const widgetId = `${widget.name}__${i}${Math.random().toString(36).slice(2)}`;
349
- return {
350
- id: widgetId,
351
- layout: {
352
- i: widgetId,
353
- x: c.x,
354
- y: c.y,
355
- w: Math.min((_a = widget.maxWidth) != null ? _a : Number.MAX_VALUE, c.width),
356
- h: Math.min((_b = widget.maxHeight) != null ? _b : Number.MAX_VALUE, c.height),
357
- minW: widget.minWidth,
358
- maxW: widget.maxWidth,
359
- minH: widget.minHeight,
360
- maxH: widget.maxHeight,
361
- isDraggable: false,
362
- isResizable: false
363
- },
364
- settings: {},
365
- movable: conf.movable,
366
- deletable: conf.deletable,
367
- resizable: conf.resizable
368
- };
369
- });
370
- return compact(ret);
371
- };
372
- const availableWidgetsFilter = (elements) => {
373
- return elements.selectByComponentData({
374
- key: "core.extensionName"
375
- }).getElements().flatMap((elem) => {
376
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
377
- const config = getComponentData(elem, "home.widget.config");
378
- return [
379
- WidgetSchema.parse({
380
- component: elem,
381
- name: getComponentData(elem, "core.extensionName"),
382
- title: getComponentData(elem, "title"),
383
- description: getComponentData(elem, "description"),
384
- settingsSchema: (_a = config == null ? void 0 : config.settings) == null ? void 0 : _a.schema,
385
- uiSchema: (_b = config == null ? void 0 : config.settings) == null ? void 0 : _b.uiSchema,
386
- width: (_d = (_c = config == null ? void 0 : config.layout) == null ? void 0 : _c.width) == null ? void 0 : _d.defaultColumns,
387
- minWidth: (_f = (_e = config == null ? void 0 : config.layout) == null ? void 0 : _e.width) == null ? void 0 : _f.minColumns,
388
- maxWidth: (_h = (_g = config == null ? void 0 : config.layout) == null ? void 0 : _g.width) == null ? void 0 : _h.maxColumns,
389
- height: (_j = (_i = config == null ? void 0 : config.layout) == null ? void 0 : _i.height) == null ? void 0 : _j.defaultRows,
390
- minHeight: (_l = (_k = config == null ? void 0 : config.layout) == null ? void 0 : _k.height) == null ? void 0 : _l.minRows,
391
- maxHeight: (_n = (_m = config == null ? void 0 : config.layout) == null ? void 0 : _m.height) == null ? void 0 : _n.maxRows
392
- })
393
- ];
394
- });
395
- };
396
- const CustomHomepageGrid = (props) => {
397
- var _a;
398
- const styles = useStyles();
399
- const theme = useTheme();
400
- const availableWidgets = useElementFilter(
401
- props.children,
402
- availableWidgetsFilter,
403
- [props]
404
- );
405
- const defaultLayout = useMemo(() => {
406
- return props.config ? convertConfigToDefaultWidgets(props.config, availableWidgets) : [];
407
- }, [props.config, availableWidgets]);
408
- const [widgets, setWidgets] = useHomeStorage(defaultLayout);
409
- const [addWidgetDialogOpen, setAddWidgetDialogOpen] = React.useState(false);
410
- const editModeOn = widgets.find((w) => w.layout.isResizable) !== void 0;
411
- const [editMode, setEditMode] = React.useState(editModeOn);
412
- const getWidgetByName = (name) => {
413
- return availableWidgets.find((widget) => widget.name === name);
414
- };
415
- const getWidgetNameFromKey = (key) => {
416
- return key.split("__")[0];
417
- };
418
- const handleAdd = (widget) => {
419
- var _a2, _b, _c, _d;
420
- const widgetId = `${widget.name}__${widgets.length + 1}${Math.random().toString(36).slice(2)}`;
421
- setWidgets([
422
- ...widgets,
423
- {
424
- id: widgetId,
425
- layout: {
426
- i: widgetId,
427
- x: 0,
428
- y: Math.max(...widgets.map((w) => w.layout.y + w.layout.h)) + 1,
429
- w: Math.min((_a2 = widget.maxWidth) != null ? _a2 : Number.MAX_VALUE, (_b = widget.width) != null ? _b : 12),
430
- h: Math.min((_c = widget.maxHeight) != null ? _c : Number.MAX_VALUE, (_d = widget.height) != null ? _d : 4),
431
- minW: widget.minWidth,
432
- maxW: widget.maxWidth,
433
- minH: widget.minHeight,
434
- maxH: widget.maxHeight,
435
- isResizable: editMode,
436
- isDraggable: editMode
437
- },
438
- settings: {},
439
- movable: widget.movable,
440
- deletable: widget.deletable,
441
- resizable: widget.resizable
442
- }
443
- ]);
444
- setAddWidgetDialogOpen(false);
445
- };
446
- const handleRemove = (widgetId) => {
447
- setWidgets(widgets.filter((w) => w.id !== widgetId));
448
- };
449
- const handleSettingsSave = (widgetId, widgetSettings) => {
450
- const idx = widgets.findIndex((w) => w.id === widgetId);
451
- if (idx >= 0) {
452
- const widget = widgets[idx];
453
- widget.settings = widgetSettings;
454
- widgets[idx] = widget;
455
- setWidgets(widgets);
456
- }
457
- };
458
- const clearLayout = () => {
459
- setWidgets([]);
460
- };
461
- const changeEditMode = (mode) => {
462
- setEditMode(mode);
463
- setWidgets(
464
- widgets.map((w) => {
465
- const resizable = w.resizable === false ? false : mode;
466
- const movable = w.movable === false ? false : mode;
467
- return {
468
- ...w,
469
- layout: { ...w.layout, isDraggable: movable, isResizable: resizable }
470
- };
471
- })
472
- );
473
- };
474
- const handleLayoutChange = (newLayout, _) => {
475
- if (editMode) {
476
- const newWidgets = newLayout.map((l) => {
477
- const widget = widgets.find((w) => w.id === l.i);
478
- return {
479
- ...widget,
480
- layout: l
481
- };
482
- });
483
- setWidgets(newWidgets);
484
- }
485
- };
486
- const handleRestoreDefaultConfig = () => {
487
- setWidgets(
488
- defaultLayout.map((w) => {
489
- const resizable = w.resizable === false ? false : editMode;
490
- const movable = w.movable === false ? false : editMode;
491
- return {
492
- ...w,
493
- layout: {
494
- ...w.layout,
495
- isDraggable: movable,
496
- isResizable: resizable
497
- }
498
- };
499
- })
500
- );
501
- };
502
- return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ContentHeader, { title: "" }, /* @__PURE__ */ React.createElement(
503
- CustomHomepageButtons,
504
- {
505
- editMode,
506
- numWidgets: widgets.length,
507
- clearLayout,
508
- setAddWidgetDialogOpen,
509
- changeEditMode,
510
- defaultConfigAvailable: props.config !== void 0,
511
- restoreDefault: handleRestoreDefaultConfig
512
- }
513
- )), /* @__PURE__ */ React.createElement(
514
- Dialog,
515
- {
516
- open: addWidgetDialogOpen,
517
- onClose: () => setAddWidgetDialogOpen(false)
518
- },
519
- /* @__PURE__ */ React.createElement(AddWidgetDialog, { widgets: availableWidgets, handleAdd })
520
- ), !editMode && widgets.length === 0 && /* @__PURE__ */ React.createElement(Typography, { variant: "h5", align: "center" }, "No widgets added. Start by clicking the 'Add widget' button."), /* @__PURE__ */ React.createElement(
521
- ResponsiveGrid,
522
- {
523
- className: styles.responsiveGrid,
524
- measureBeforeMount: true,
525
- compactType: props.compactType,
526
- style: props.style,
527
- allowOverlap: props.allowOverlap,
528
- preventCollision: props.preventCollision,
529
- draggableCancel: ".overlayGridItem,.widgetSettingsDialog,.disabled",
530
- containerPadding: props.containerPadding,
531
- margin: props.containerMargin,
532
- breakpoints: props.breakpoints ? props.breakpoints : theme.breakpoints.values,
533
- cols: props.cols ? props.cols : { xl: 12, lg: 12, md: 10, sm: 6, xs: 4, xxs: 2 },
534
- rowHeight: (_a = props.rowHeight) != null ? _a : 60,
535
- onLayoutChange: handleLayoutChange,
536
- layouts: { xl: widgets.map((w) => w.layout) }
537
- },
538
- widgets.map((w) => {
539
- var _a2;
540
- const l = w.layout;
541
- const widgetName = getWidgetNameFromKey(l.i);
542
- const widget = getWidgetByName(widgetName);
543
- if (!widget || !widget.component) {
544
- return null;
545
- }
546
- const widgetProps = {
547
- ...widget.component.props,
548
- ...(_a2 = w.settings) != null ? _a2 : {}
549
- };
550
- return /* @__PURE__ */ React.createElement(
551
- "div",
552
- {
553
- key: l.i,
554
- className: `${styles.widgetWrapper} ${editMode && "edit"} ${w.movable === false && "disabled"}`
555
- },
556
- /* @__PURE__ */ React.createElement(ErrorBoundary, null, /* @__PURE__ */ React.createElement(widget.component.type, { ...widgetProps })),
557
- editMode && /* @__PURE__ */ React.createElement(
558
- WidgetSettingsOverlay,
559
- {
560
- id: l.i,
561
- widget,
562
- handleRemove,
563
- handleSettingsSave,
564
- settings: w.settings,
565
- deletable: w.deletable
566
- }
567
- )
568
- );
569
- })
570
- ));
571
- };
572
-
573
- const getToEntityRef = ({
574
- rootPath = "catalog",
575
- stringifyEntityRefImpl = stringifyEntityRef
576
- } = {}) => ({ pathname }) => {
577
- const regex = new RegExp(
578
- `^/${rootPath}/(?<namespace>[^/]+)/(?<kind>[^/]+)/(?<name>[^/]+)`
579
- );
580
- const result = regex.exec(pathname);
581
- if (!result || !(result == null ? void 0 : result.groups))
582
- return void 0;
583
- const entity = {
584
- namespace: result.groups.namespace,
585
- kind: result.groups.kind,
586
- name: result.groups.name
587
- };
588
- return stringifyEntityRefImpl(entity);
589
- };
590
- const getVisitName = ({ rootPath = "catalog", document = global.document } = {}) => ({ pathname }) => {
591
- const regex = new RegExp(
592
- `^/${rootPath}/(?<namespace>[^/]+)/(?<kind>[^/]+)/(?<name>[^/]+)`
593
- );
594
- let result = regex.exec(pathname);
595
- if (result && (result == null ? void 0 : result.groups))
596
- return result.groups.name;
597
- result = /^\/(?<name>[^\/]+)$/.exec(pathname);
598
- if (result && (result == null ? void 0 : result.groups))
599
- return result.groups.name;
600
- return document.title;
601
- };
602
- const VisitListener = ({
603
- children,
604
- toEntityRef,
605
- visitName
606
- }) => {
607
- const visitsApi = useApi(visitsApiRef);
608
- const { pathname } = useLocation();
609
- const toEntityRefImpl = toEntityRef != null ? toEntityRef : getToEntityRef();
610
- const visitNameImpl = visitName != null ? visitName : getVisitName();
611
- useEffect(() => {
612
- const requestId = requestAnimationFrame(() => {
613
- visitsApi.save({
614
- visit: {
615
- name: visitNameImpl({ pathname }),
616
- pathname,
617
- entityRef: toEntityRefImpl({ pathname })
618
- }
619
- });
620
- });
621
- return () => cancelAnimationFrame(requestId);
622
- }, [visitsApi, pathname, toEntityRefImpl, visitNameImpl]);
623
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children);
624
- };
625
-
626
- export { CustomHomepageGrid as C, VisitListener as V, isOperator as i, visitsApiRef as v };
627
- //# sourceMappingURL=VisitListener-dDLtFiIW.esm.js.map