@red-hat-developer-hub/backstage-plugin-adoption-insights 0.2.1 → 0.3.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/CHANGELOG.md +31 -0
- package/dist/components/ActiveUsers/ActiveUsers.esm.js +26 -11
- package/dist/components/ActiveUsers/ActiveUsers.esm.js.map +1 -1
- package/dist/components/ActiveUsers/CustomLegend.esm.js +4 -2
- package/dist/components/ActiveUsers/CustomLegend.esm.js.map +1 -1
- package/dist/components/ActiveUsers/ExportCSVButton.esm.js +9 -3
- package/dist/components/ActiveUsers/ExportCSVButton.esm.js.map +1 -1
- package/dist/components/AdoptionInsightsPage/AdoptionInsightsPage.esm.js +3 -1
- package/dist/components/AdoptionInsightsPage/AdoptionInsightsPage.esm.js.map +1 -1
- package/dist/components/CardFooter/TableFooterPagination.esm.js +37 -6
- package/dist/components/CardFooter/TableFooterPagination.esm.js.map +1 -1
- package/dist/components/CatalogEntities/CatalogEntities.esm.js +11 -7
- package/dist/components/CatalogEntities/CatalogEntities.esm.js.map +1 -1
- package/dist/components/CatalogEntities/FilterDropdown.esm.js +6 -4
- package/dist/components/CatalogEntities/FilterDropdown.esm.js.map +1 -1
- package/dist/components/Common/ChartTooltip.esm.js +22 -11
- package/dist/components/Common/ChartTooltip.esm.js.map +1 -1
- package/dist/components/Common/EmptyChartState.esm.js +3 -1
- package/dist/components/Common/EmptyChartState.esm.js.map +1 -1
- package/dist/components/Common/PermissionRequiredState.esm.js +7 -7
- package/dist/components/Common/PermissionRequiredState.esm.js.map +1 -1
- package/dist/components/Header/Header.esm.js +117 -122
- package/dist/components/Header/Header.esm.js.map +1 -1
- package/dist/components/Plugins/Plugins.esm.js +71 -66
- package/dist/components/Plugins/Plugins.esm.js.map +1 -1
- package/dist/components/Searches/Searches.esm.js +28 -13
- package/dist/components/Searches/Searches.esm.js.map +1 -1
- package/dist/components/Techdocs/Techdocs.esm.js +84 -76
- package/dist/components/Techdocs/Techdocs.esm.js.map +1 -1
- package/dist/components/Templates/Templates.esm.js +74 -66
- package/dist/components/Templates/Templates.esm.js.map +1 -1
- package/dist/components/Trans.esm.js +9 -0
- package/dist/components/Trans.esm.js.map +1 -0
- package/dist/components/Users/Info.esm.js +3 -1
- package/dist/components/Users/Info.esm.js.map +1 -1
- package/dist/components/Users/Tooltip.esm.js +4 -6
- package/dist/components/Users/Tooltip.esm.js.map +1 -1
- package/dist/components/Users/Users.esm.js +18 -10
- package/dist/components/Users/Users.esm.js.map +1 -1
- package/dist/hooks/useLanguage.esm.js +7 -0
- package/dist/hooks/useLanguage.esm.js.map +1 -0
- package/dist/hooks/useTranslation.esm.js +8 -0
- package/dist/hooks/useTranslation.esm.js.map +1 -0
- package/dist/index.d.ts +87 -1
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/translations/de.esm.js +82 -0
- package/dist/translations/de.esm.js.map +1 -0
- package/dist/translations/es.esm.js +82 -0
- package/dist/translations/es.esm.js.map +1 -0
- package/dist/translations/fr.esm.js +82 -0
- package/dist/translations/fr.esm.js.map +1 -0
- package/dist/translations/index.esm.js +15 -0
- package/dist/translations/index.esm.js.map +1 -0
- package/dist/translations/it.esm.js +82 -0
- package/dist/translations/it.esm.js.map +1 -0
- package/dist/translations/ref.esm.js +116 -0
- package/dist/translations/ref.esm.js.map +1 -0
- package/dist/utils/constants.esm.js +20 -21
- package/dist/utils/constants.esm.js.map +1 -1
- package/dist/utils/utils.esm.js +95 -44
- package/dist/utils/utils.esm.js.map +1 -1
- package/package.json +19 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @red-hat-developer-hub/backstage-plugin-adoption-insights
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2470f72: Add internationalization (i18n) support with German and French translations.
|
|
8
|
+
- 6673ba3: Backstage version bump to v1.42.5
|
|
9
|
+
|
|
10
|
+
### Patch Changes
|
|
11
|
+
|
|
12
|
+
- 192c262: Update label from techdocs to TechDocs in UI
|
|
13
|
+
- 67e9f96: Fixed CSV export filename to include timestamp for better file identification and to avoid naming conflicts. Active Users CSV exports now use format "active_users_YYYY-MM-DD_HH-mm-ss-SSS.csv" instead of generic "active_users"
|
|
14
|
+
- 25fcc52: Pagination and title consistency improvements:
|
|
15
|
+
|
|
16
|
+
- Fixed dynamic "Top X" pagination options to adapt to actual item count, resolving misleading filter options when dataset is smaller than defaults
|
|
17
|
+
- Added "All" option for datasets smaller than maxDefaultOption (20 items)
|
|
18
|
+
- Improved component title consistency across the UI
|
|
19
|
+
|
|
20
|
+
- e7f6aba: Fixed Adoption Insights header background color by removing custom background style override that was causing wrong theming
|
|
21
|
+
- 617de8b: - Fixed confusing text in ActiveUsers and Searches components by replacing "were conducted" with professional analytics terminology
|
|
22
|
+
- Updated text to use "Average peak active user count" and "Average search count" for better clarity
|
|
23
|
+
- Enhanced time period text to properly handle all grouping types (hourly, daily, weekly, monthly) instead of only supporting hour and day
|
|
24
|
+
- 0dd7b78: Align legends in Active users card, display trends on initial load, and remove empty space in no results card
|
|
25
|
+
- b887a58: French translation updated
|
|
26
|
+
- 5eeb69a: Updated dependency `@mui/lab` to `5.0.0-alpha.177`.
|
|
27
|
+
Updated dependency `date-fns-tz` to `1.3.8`.
|
|
28
|
+
- 86cf463: Updated dependency `@red-hat-developer-hub/backstage-plugin-theme` to `^0.10.0`.
|
|
29
|
+
- c2501eb: Updated dependency `@mui/icons-material` to `5.18.0`.
|
|
30
|
+
Updated dependency `@mui/material` to `5.18.0`.
|
|
31
|
+
- Updated dependencies [6673ba3]
|
|
32
|
+
- @red-hat-developer-hub/backstage-plugin-adoption-insights-common@0.4.0
|
|
33
|
+
|
|
3
34
|
## 0.2.1
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
|
@@ -7,34 +7,39 @@ import { ResponsiveContainer, AreaChart, CartesianGrid, XAxis, YAxis, Tooltip, A
|
|
|
7
7
|
import CardWrapper from '../CardWrapper/CardWrapper.esm.js';
|
|
8
8
|
import CustomCursor from '../Common/CustomCursor.esm.js';
|
|
9
9
|
import CustomLegend from './CustomLegend.esm.js';
|
|
10
|
-
import { getAverage, getXAxisTickValues, getXAxisformat } from '../../utils/utils.esm.js';
|
|
10
|
+
import { getGroupingLabel, getAverage, getXAxisTickValues, getXAxisformat, formatNumber } from '../../utils/utils.esm.js';
|
|
11
11
|
import { useActiveUsers } from '../../hooks/useActiveUsers.esm.js';
|
|
12
12
|
import { Typography } from '@material-ui/core';
|
|
13
13
|
import ExportCSVButton from './ExportCSVButton.esm.js';
|
|
14
14
|
import EmptyChartState from '../Common/EmptyChartState.esm.js';
|
|
15
15
|
import ChartTooltip from '../Common/ChartTooltip.esm.js';
|
|
16
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
17
|
+
import { useLanguage } from '../../hooks/useLanguage.esm.js';
|
|
18
|
+
import { Trans } from '../Trans.esm.js';
|
|
16
19
|
|
|
17
20
|
const ActiveUsers = () => {
|
|
18
21
|
const theme = useTheme();
|
|
19
22
|
const isDarkMode = theme.palette.mode === "dark";
|
|
23
|
+
const { t } = useTranslation();
|
|
24
|
+
const locale = useLanguage();
|
|
20
25
|
const { activeUsers, loading, error } = useActiveUsers();
|
|
21
26
|
const { data, grouping = "daily" } = activeUsers;
|
|
22
27
|
if (error) {
|
|
23
|
-
return /* @__PURE__ */ jsx(CardWrapper, { title: "
|
|
28
|
+
return /* @__PURE__ */ jsx(CardWrapper, { title: t("activeUsers.title"), children: /* @__PURE__ */ jsx(ResponseErrorPanel, { error }) });
|
|
24
29
|
}
|
|
25
30
|
if (!data || data?.length === 0 || !data?.[0] && !loading) {
|
|
26
|
-
return /* @__PURE__ */ jsx(CardWrapper, { title: "
|
|
31
|
+
return /* @__PURE__ */ jsx(CardWrapper, { title: t("activeUsers.title"), children: /* @__PURE__ */ jsx(
|
|
27
32
|
Box,
|
|
28
33
|
{
|
|
29
34
|
display: "flex",
|
|
30
35
|
justifyContent: "center",
|
|
31
36
|
alignItems: "center",
|
|
32
|
-
|
|
37
|
+
minHeight: 80,
|
|
33
38
|
children: /* @__PURE__ */ jsx(EmptyChartState, {})
|
|
34
39
|
}
|
|
35
40
|
) });
|
|
36
41
|
}
|
|
37
|
-
return /* @__PURE__ */ jsx(CardWrapper, { title: "
|
|
42
|
+
return /* @__PURE__ */ jsx(CardWrapper, { title: t("activeUsers.title"), filter: /* @__PURE__ */ jsx(ExportCSVButton, {}), children: loading ? /* @__PURE__ */ jsx(
|
|
38
43
|
Box,
|
|
39
44
|
{
|
|
40
45
|
display: "flex",
|
|
@@ -45,11 +50,21 @@ const ActiveUsers = () => {
|
|
|
45
50
|
}
|
|
46
51
|
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
47
52
|
/* @__PURE__ */ jsxs(Typography, { style: { margin: "20px 36px" }, children: [
|
|
48
|
-
|
|
49
|
-
"en-Us"
|
|
50
|
-
)} active users per ${grouping === "hourly" ? "hour" : "day"}` }),
|
|
53
|
+
t("activeUsers.averagePrefix"),
|
|
51
54
|
" ",
|
|
52
|
-
"
|
|
55
|
+
/* @__PURE__ */ jsx("b", { children: /* @__PURE__ */ jsx(
|
|
56
|
+
Trans,
|
|
57
|
+
{
|
|
58
|
+
message: "activeUsers.averageText",
|
|
59
|
+
params: {
|
|
60
|
+
count: Math.round(
|
|
61
|
+
getAverage(data, "total_users")
|
|
62
|
+
).toLocaleString("en-US"),
|
|
63
|
+
period: getGroupingLabel(grouping, t, "activeUsers")
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
) }),
|
|
67
|
+
t("activeUsers.averageSuffix")
|
|
53
68
|
] }),
|
|
54
69
|
/* @__PURE__ */ jsx(Box, { sx: { height: 310, mt: 4, mb: 4, ml: 0, mr: 0 }, children: /* @__PURE__ */ jsx(ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ jsxs(
|
|
55
70
|
AreaChart,
|
|
@@ -89,7 +104,7 @@ const ActiveUsers = () => {
|
|
|
89
104
|
XAxis,
|
|
90
105
|
{
|
|
91
106
|
dataKey: "date",
|
|
92
|
-
tickFormatter: (date) => getXAxisformat(date, grouping),
|
|
107
|
+
tickFormatter: (date) => getXAxisformat(date, grouping, locale),
|
|
93
108
|
ticks: getXAxisTickValues(data, grouping),
|
|
94
109
|
tick: { fill: theme.palette.text.primary },
|
|
95
110
|
axisLine: false,
|
|
@@ -104,7 +119,7 @@ const ActiveUsers = () => {
|
|
|
104
119
|
tick: { fill: theme.palette.text.primary },
|
|
105
120
|
tickLine: false,
|
|
106
121
|
axisLine: false,
|
|
107
|
-
tickFormatter: (value) => value
|
|
122
|
+
tickFormatter: (value) => formatNumber(value, {}, locale),
|
|
108
123
|
tickMargin: 20
|
|
109
124
|
}
|
|
110
125
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActiveUsers.esm.js","sources":["../../../src/components/ActiveUsers/ActiveUsers.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport { ResponseErrorPanel } from '@backstage/core-components';\nimport Box from '@mui/material/Box';\nimport { useTheme } from '@mui/material/styles';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport {\n AreaChart,\n CartesianGrid,\n ResponsiveContainer,\n XAxis,\n YAxis,\n Tooltip,\n Area,\n Legend,\n} from 'recharts';\n\nimport CardWrapper from '../CardWrapper';\nimport CustomCursor from '../Common/CustomCursor';\nimport CustomLegend from './CustomLegend';\nimport {\n getAverage,\n getXAxisformat,\n getXAxisTickValues,\n} from '../../utils/utils';\nimport { useActiveUsers } from '../../hooks/useActiveUsers';\nimport { Typography } from '@material-ui/core';\nimport ExportCSVButton from './ExportCSVButton';\nimport EmptyChartState from '../Common/EmptyChartState';\nimport ChartTooltip from '../Common/ChartTooltip';\n\nconst ActiveUsers = () => {\n const theme = useTheme();\n const isDarkMode = theme.palette.mode === 'dark';\n\n const { activeUsers, loading, error } = useActiveUsers();\n const { data, grouping = 'daily' } = activeUsers;\n if (error) {\n return (\n <CardWrapper title=\"Active users\">\n <ResponseErrorPanel error={error} />\n </CardWrapper>\n );\n }\n\n if (!data || data?.length === 0 || (!data?.[0] && !loading)) {\n return (\n <CardWrapper title=\"Active users\">\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n height={200}\n >\n <EmptyChartState />\n </Box>\n </CardWrapper>\n );\n }\n\n return (\n <CardWrapper title=\"Active users\" filter={<ExportCSVButton />}>\n {loading ? (\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n height={200}\n >\n <CircularProgress />\n </Box>\n ) : (\n <>\n <Typography style={{ margin: '20px 36px' }}>\n <b>\n {`${Math.round(getAverage(data, 'total_users')).toLocaleString(\n 'en-Us',\n )} active users per ${grouping === 'hourly' ? 'hour' : 'day'}`}\n </b>{' '}\n were conducted during this period.\n </Typography>\n <Box sx={{ height: 310, mt: 4, mb: 4, ml: 0, mr: 0 }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart\n data={data}\n margin={{ top: 10, right: 50, left: 20, bottom: 0 }}\n key={JSON.stringify(data.map(d => d))}\n >\n <defs>\n <linearGradient id=\"new_users\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"5%\" stopColor=\"#1976d2\" stopOpacity={0.8} />\n <stop offset=\"95%\" stopColor=\"#1976d2\" stopOpacity={0.2} />\n </linearGradient>\n <linearGradient\n id=\"returning_users\"\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop offset=\"5%\" stopColor=\"#B8BBBE\" stopOpacity={0.8} />\n <stop offset=\"95%\" stopColor=\"#B8BBBE\" stopOpacity={0.2} />\n </linearGradient>\n </defs>\n\n <CartesianGrid\n stroke={isDarkMode ? '#666' : '#E5E7EB'}\n strokeDasharray={0}\n vertical={false}\n />\n\n <XAxis\n dataKey=\"date\"\n tickFormatter={date => getXAxisformat(date, grouping)}\n ticks={getXAxisTickValues(data, grouping)}\n tick={{ fill: theme.palette.text.primary }}\n axisLine={false}\n tickLine={false}\n padding={{ left: 30, right: 30 }}\n tickMargin={10}\n />\n <YAxis\n tick={{ fill: theme.palette.text.primary }}\n tickLine={false}\n axisLine={false}\n tickFormatter={value => value.toLocaleString('en-Us')}\n tickMargin={20}\n />\n <Tooltip\n cursor={<CustomCursor cursorHeight={250} />}\n content={<ChartTooltip grouping={grouping} />}\n />\n <Area\n type=\"linear\"\n dataKey=\"returning_users\"\n stroke=\"#555\"\n fill=\"url(#returning_users)\"\n strokeWidth={1}\n />\n <Area\n type=\"linear\"\n dataKey=\"new_users\"\n stroke=\"#1976d2\"\n fill=\"url(#new_users)\"\n strokeWidth={1}\n />\n <Legend content={<CustomLegend />} />\n </AreaChart>\n </ResponsiveContainer>\n </Box>\n </>\n )}\n </CardWrapper>\n );\n};\n\nexport default ActiveUsers;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ActiveUsers.esm.js","sources":["../../../src/components/ActiveUsers/ActiveUsers.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport { ResponseErrorPanel } from '@backstage/core-components';\nimport Box from '@mui/material/Box';\nimport { useTheme } from '@mui/material/styles';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport {\n AreaChart,\n CartesianGrid,\n ResponsiveContainer,\n XAxis,\n YAxis,\n Tooltip,\n Area,\n Legend,\n} from 'recharts';\n\nimport CardWrapper from '../CardWrapper';\nimport CustomCursor from '../Common/CustomCursor';\nimport CustomLegend from './CustomLegend';\nimport {\n getAverage,\n getXAxisformat,\n getXAxisTickValues,\n formatNumber,\n getGroupingLabel,\n} from '../../utils/utils';\nimport { useActiveUsers } from '../../hooks/useActiveUsers';\nimport { Typography } from '@material-ui/core';\nimport ExportCSVButton from './ExportCSVButton';\nimport EmptyChartState from '../Common/EmptyChartState';\nimport ChartTooltip from '../Common/ChartTooltip';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { useLanguage } from '../../hooks/useLanguage';\nimport { Trans } from '../Trans';\n\nconst ActiveUsers = () => {\n const theme = useTheme();\n const isDarkMode = theme.palette.mode === 'dark';\n const { t } = useTranslation();\n const locale = useLanguage();\n\n const { activeUsers, loading, error } = useActiveUsers();\n const { data, grouping = 'daily' } = activeUsers;\n if (error) {\n return (\n <CardWrapper title={t('activeUsers.title')}>\n <ResponseErrorPanel error={error} />\n </CardWrapper>\n );\n }\n\n if (!data || data?.length === 0 || (!data?.[0] && !loading)) {\n return (\n <CardWrapper title={t('activeUsers.title')}>\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n minHeight={80}\n >\n <EmptyChartState />\n </Box>\n </CardWrapper>\n );\n }\n\n return (\n <CardWrapper title={t('activeUsers.title')} filter={<ExportCSVButton />}>\n {loading ? (\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n height={200}\n >\n <CircularProgress />\n </Box>\n ) : (\n <>\n <Typography style={{ margin: '20px 36px' }}>\n {t('activeUsers.averagePrefix')}{' '}\n <b>\n <Trans\n message=\"activeUsers.averageText\"\n params={{\n count: Math.round(\n getAverage(data, 'total_users'),\n ).toLocaleString('en-US'),\n period: getGroupingLabel(grouping, t, 'activeUsers'),\n }}\n />\n </b>\n {t('activeUsers.averageSuffix')}\n </Typography>\n <Box sx={{ height: 310, mt: 4, mb: 4, ml: 0, mr: 0 }}>\n <ResponsiveContainer width=\"100%\" height=\"100%\">\n <AreaChart\n data={data}\n margin={{ top: 10, right: 50, left: 20, bottom: 0 }}\n key={JSON.stringify(data.map(d => d))}\n >\n <defs>\n <linearGradient id=\"new_users\" x1=\"0\" y1=\"0\" x2=\"0\" y2=\"1\">\n <stop offset=\"5%\" stopColor=\"#1976d2\" stopOpacity={0.8} />\n <stop offset=\"95%\" stopColor=\"#1976d2\" stopOpacity={0.2} />\n </linearGradient>\n <linearGradient\n id=\"returning_users\"\n x1=\"0\"\n y1=\"0\"\n x2=\"0\"\n y2=\"1\"\n >\n <stop offset=\"5%\" stopColor=\"#B8BBBE\" stopOpacity={0.8} />\n <stop offset=\"95%\" stopColor=\"#B8BBBE\" stopOpacity={0.2} />\n </linearGradient>\n </defs>\n\n <CartesianGrid\n stroke={isDarkMode ? '#666' : '#E5E7EB'}\n strokeDasharray={0}\n vertical={false}\n />\n\n <XAxis\n dataKey=\"date\"\n tickFormatter={date => getXAxisformat(date, grouping, locale)}\n ticks={getXAxisTickValues(data, grouping)}\n tick={{ fill: theme.palette.text.primary }}\n axisLine={false}\n tickLine={false}\n padding={{ left: 30, right: 30 }}\n tickMargin={10}\n />\n <YAxis\n tick={{ fill: theme.palette.text.primary }}\n tickLine={false}\n axisLine={false}\n tickFormatter={value => formatNumber(value, {}, locale)}\n tickMargin={20}\n />\n <Tooltip\n cursor={<CustomCursor cursorHeight={250} />}\n content={<ChartTooltip grouping={grouping} />}\n />\n <Area\n type=\"linear\"\n dataKey=\"returning_users\"\n stroke=\"#555\"\n fill=\"url(#returning_users)\"\n strokeWidth={1}\n />\n <Area\n type=\"linear\"\n dataKey=\"new_users\"\n stroke=\"#1976d2\"\n fill=\"url(#new_users)\"\n strokeWidth={1}\n />\n <Legend content={<CustomLegend />} />\n </AreaChart>\n </ResponsiveContainer>\n </Box>\n </>\n )}\n </CardWrapper>\n );\n};\n\nexport default ActiveUsers;\n"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
2
|
import Typography from '@mui/material/Typography';
|
|
3
3
|
import { useTheme } from '@mui/material/styles';
|
|
4
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
4
5
|
|
|
5
6
|
const CustomLegend = (props) => {
|
|
6
7
|
const theme = useTheme();
|
|
7
8
|
const { payload } = props;
|
|
9
|
+
const { t } = useTranslation();
|
|
8
10
|
return /* @__PURE__ */ jsx(
|
|
9
11
|
"div",
|
|
10
12
|
{
|
|
@@ -26,7 +28,7 @@ const CustomLegend = (props) => {
|
|
|
26
28
|
{
|
|
27
29
|
style: {
|
|
28
30
|
width: 20,
|
|
29
|
-
height:
|
|
31
|
+
height: 4,
|
|
30
32
|
backgroundColor: entry.color
|
|
31
33
|
}
|
|
32
34
|
}
|
|
@@ -48,7 +50,7 @@ const CustomLegend = (props) => {
|
|
|
48
50
|
{
|
|
49
51
|
variant: "body2",
|
|
50
52
|
style: { color: theme.palette.text.primary, fontSize: "0.875rem" },
|
|
51
|
-
children: entry.value === "new_users" ? "
|
|
53
|
+
children: entry.value === "new_users" ? t("activeUsers.legend.newUsers") : t("activeUsers.legend.returningUsers")
|
|
52
54
|
}
|
|
53
55
|
)
|
|
54
56
|
]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CustomLegend.esm.js","sources":["../../../src/components/ActiveUsers/CustomLegend.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport Typography from '@mui/material/Typography';\nimport { useTheme } from '@mui/material/styles';\n\nconst CustomLegend = (props: any) => {\n const theme = useTheme();\n const { payload } = props;\n\n return (\n <div\n style={{\n display: 'flex',\n gap: 16,\n alignItems: 'center',\n marginLeft: 50,\n paddingTop: 10,\n }}\n >\n {payload.map((entry: any) => (\n <div\n key={entry.value}\n style={{ display: 'flex', alignItems: 'center', gap: 4 }}\n >\n <div>\n <div\n style={{\n width: 20,\n height:
|
|
1
|
+
{"version":3,"file":"CustomLegend.esm.js","sources":["../../../src/components/ActiveUsers/CustomLegend.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport Typography from '@mui/material/Typography';\nimport { useTheme } from '@mui/material/styles';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nconst CustomLegend = (props: any) => {\n const theme = useTheme();\n const { payload } = props;\n const { t } = useTranslation();\n\n return (\n <div\n style={{\n display: 'flex',\n gap: 16,\n alignItems: 'center',\n marginLeft: 50,\n paddingTop: 10,\n }}\n >\n {payload.map((entry: any) => (\n <div\n key={entry.value}\n style={{ display: 'flex', alignItems: 'center', gap: 4 }}\n >\n <div>\n <div\n style={{\n width: 20,\n height: 4,\n backgroundColor: entry.color,\n }}\n />\n <div\n style={{\n width: 20,\n height: 4,\n backgroundColor: entry.color,\n opacity: '0.4',\n }}\n />\n </div>\n <Typography\n variant=\"body2\"\n style={{ color: theme.palette.text.primary, fontSize: '0.875rem' }}\n >\n {entry.value === 'new_users'\n ? t('activeUsers.legend.newUsers')\n : t('activeUsers.legend.returningUsers')}\n </Typography>\n </div>\n ))}\n </div>\n );\n};\n\nexport default CustomLegend;\n"],"names":[],"mappings":";;;;;AAmBM,MAAA,YAAA,GAAe,CAAC,KAAe,KAAA;AACnC,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAM,MAAA,EAAE,SAAY,GAAA,KAAA;AACpB,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EACE,uBAAA,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,KAAO,EAAA;AAAA,QACL,OAAS,EAAA,MAAA;AAAA,QACT,GAAK,EAAA,EAAA;AAAA,QACL,UAAY,EAAA,QAAA;AAAA,QACZ,UAAY,EAAA,EAAA;AAAA,QACZ,UAAY,EAAA;AAAA,OACd;AAAA,MAEC,QAAA,EAAA,OAAA,CAAQ,GAAI,CAAA,CAAC,KACZ,qBAAA,IAAA;AAAA,QAAC,KAAA;AAAA,QAAA;AAAA,UAEC,OAAO,EAAE,OAAA,EAAS,QAAQ,UAAY,EAAA,QAAA,EAAU,KAAK,CAAE,EAAA;AAAA,UAEvD,QAAA,EAAA;AAAA,4BAAA,IAAA,CAAC,KACC,EAAA,EAAA,QAAA,EAAA;AAAA,8BAAA,GAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,KAAO,EAAA;AAAA,oBACL,KAAO,EAAA,EAAA;AAAA,oBACP,MAAQ,EAAA,CAAA;AAAA,oBACR,iBAAiB,KAAM,CAAA;AAAA;AACzB;AAAA,eACF;AAAA,8BACA,GAAA;AAAA,gBAAC,KAAA;AAAA,gBAAA;AAAA,kBACC,KAAO,EAAA;AAAA,oBACL,KAAO,EAAA,EAAA;AAAA,oBACP,MAAQ,EAAA,CAAA;AAAA,oBACR,iBAAiB,KAAM,CAAA,KAAA;AAAA,oBACvB,OAAS,EAAA;AAAA;AACX;AAAA;AACF,aACF,EAAA,CAAA;AAAA,4BACA,GAAA;AAAA,cAAC,UAAA;AAAA,cAAA;AAAA,gBACC,OAAQ,EAAA,OAAA;AAAA,gBACR,KAAA,EAAO,EAAE,KAAO,EAAA,KAAA,CAAM,QAAQ,IAAK,CAAA,OAAA,EAAS,UAAU,UAAW,EAAA;AAAA,gBAEhE,gBAAM,KAAU,KAAA,WAAA,GACb,EAAE,6BAA6B,CAAA,GAC/B,EAAE,mCAAmC;AAAA;AAAA;AAC3C;AAAA,SAAA;AAAA,QA3BK,KAAM,CAAA;AAAA,OA6Bd;AAAA;AAAA,GACH;AAEJ;;;;"}
|
|
@@ -8,21 +8,25 @@ import { useTheme } from '@mui/material/styles';
|
|
|
8
8
|
import { format } from 'date-fns';
|
|
9
9
|
import { adoptionInsightsApiRef } from '../../api/index.esm.js';
|
|
10
10
|
import { useDateRange } from '../Header/DateRangeContext.esm.js';
|
|
11
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
11
12
|
|
|
12
13
|
const ExportCSVButton = () => {
|
|
13
14
|
const [loading, setLoading] = useState(false);
|
|
14
15
|
const api = useApi(adoptionInsightsApiRef);
|
|
15
16
|
const { startDateRange, endDateRange } = useDateRange();
|
|
16
17
|
const theme = useTheme();
|
|
18
|
+
const { t } = useTranslation();
|
|
17
19
|
const debounceRef = useRef(null);
|
|
18
20
|
const handleCSVDownload = async () => {
|
|
19
21
|
try {
|
|
22
|
+
const timestamp = format(/* @__PURE__ */ new Date(), "yyyy-MM-dd_HH-mm-ss-SSS");
|
|
20
23
|
await api.downloadBlob({
|
|
21
24
|
type: "active_users",
|
|
22
25
|
start_date: startDateRange ? format(startDateRange, "yyyy-MM-dd") : void 0,
|
|
23
26
|
end_date: endDateRange ? format(endDateRange, "yyyy-MM-dd") : void 0,
|
|
24
27
|
timezone: new Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
25
|
-
format: "csv"
|
|
28
|
+
format: "csv",
|
|
29
|
+
blobName: `${t("common.csvFilename")}_${timestamp}.csv`
|
|
26
30
|
});
|
|
27
31
|
} catch (error) {
|
|
28
32
|
console.error("CSV Download failed:", error);
|
|
@@ -47,7 +51,9 @@ const ExportCSVButton = () => {
|
|
|
47
51
|
minWidth: 160,
|
|
48
52
|
display: "flex",
|
|
49
53
|
alignItems: "center",
|
|
50
|
-
justifyContent: "center"
|
|
54
|
+
justifyContent: "center",
|
|
55
|
+
padding: "8px 16px"
|
|
56
|
+
// Add padding for better spacing from card border
|
|
51
57
|
},
|
|
52
58
|
children: /* @__PURE__ */ jsx(
|
|
53
59
|
Button,
|
|
@@ -66,7 +72,7 @@ const ExportCSVButton = () => {
|
|
|
66
72
|
textDecoration: "none"
|
|
67
73
|
}
|
|
68
74
|
},
|
|
69
|
-
children: loading ? "
|
|
75
|
+
children: loading ? t("common.downloading") : t("common.exportCSV")
|
|
70
76
|
}
|
|
71
77
|
)
|
|
72
78
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExportCSVButton.esm.js","sources":["../../../src/components/ActiveUsers/ExportCSVButton.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport { useRef, useState } from 'react';\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport Button from '@mui/material/Button';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\nimport Box from '@mui/material/Box';\nimport { useTheme } from '@mui/material/styles';\nimport { format } from 'date-fns';\n\nimport { adoptionInsightsApiRef } from '../../api';\nimport { useDateRange } from '../Header/DateRangeContext';\n\nconst ExportCSVButton = () => {\n const [loading, setLoading] = useState(false);\n const api = useApi(adoptionInsightsApiRef);\n const { startDateRange, endDateRange } = useDateRange();\n const theme = useTheme();\n const debounceRef = useRef<NodeJS.Timeout | null>(null);\n\n const handleCSVDownload = async () => {\n try {\n await api.downloadBlob({\n type: 'active_users',\n start_date: startDateRange\n ? format(startDateRange, 'yyyy-MM-dd')\n : undefined,\n end_date: endDateRange ? format(endDateRange, 'yyyy-MM-dd') : undefined,\n timezone: new Intl.DateTimeFormat().resolvedOptions().timeZone,\n format: 'csv',\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('CSV Download failed:', error);\n } finally {\n setLoading(false);\n }\n };\n\n const debouncedHandleCSVDownload = () => {\n setLoading(true);\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n debounceRef.current = setTimeout(() => {\n handleCSVDownload();\n }, 500);\n };\n\n return (\n <Box\n sx={{\n height: '100%',\n minWidth: 160,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }}\n >\n <Button\n variant=\"text\"\n startIcon={<FileDownloadOutlinedIcon />}\n onClick={debouncedHandleCSVDownload}\n sx={{\n color: theme.palette.primary.main,\n textTransform: 'none',\n fontSize: '1rem',\n fontWeight: 400,\n textDecoration: 'none',\n '&:hover': {\n backgroundColor: 'transparent',\n textDecoration: 'none',\n },\n }}\n >\n {loading ? '
|
|
1
|
+
{"version":3,"file":"ExportCSVButton.esm.js","sources":["../../../src/components/ActiveUsers/ExportCSVButton.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport { useRef, useState } from 'react';\n\nimport { useApi } from '@backstage/core-plugin-api';\nimport Button from '@mui/material/Button';\nimport FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';\nimport Box from '@mui/material/Box';\nimport { useTheme } from '@mui/material/styles';\nimport { format } from 'date-fns';\n\nimport { adoptionInsightsApiRef } from '../../api';\nimport { useDateRange } from '../Header/DateRangeContext';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nconst ExportCSVButton = () => {\n const [loading, setLoading] = useState(false);\n const api = useApi(adoptionInsightsApiRef);\n const { startDateRange, endDateRange } = useDateRange();\n const theme = useTheme();\n const { t } = useTranslation();\n const debounceRef = useRef<NodeJS.Timeout | null>(null);\n\n const handleCSVDownload = async () => {\n try {\n const timestamp = format(new Date(), 'yyyy-MM-dd_HH-mm-ss-SSS');\n await api.downloadBlob({\n type: 'active_users',\n start_date: startDateRange\n ? format(startDateRange, 'yyyy-MM-dd')\n : undefined,\n end_date: endDateRange ? format(endDateRange, 'yyyy-MM-dd') : undefined,\n timezone: new Intl.DateTimeFormat().resolvedOptions().timeZone,\n format: 'csv',\n blobName: `${t('common.csvFilename')}_${timestamp}.csv`,\n });\n } catch (error) {\n // eslint-disable-next-line no-console\n console.error('CSV Download failed:', error);\n } finally {\n setLoading(false);\n }\n };\n\n const debouncedHandleCSVDownload = () => {\n setLoading(true);\n if (debounceRef.current) {\n clearTimeout(debounceRef.current);\n }\n debounceRef.current = setTimeout(() => {\n handleCSVDownload();\n }, 500);\n };\n\n return (\n <Box\n sx={{\n height: '100%',\n minWidth: 160,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n padding: '8px 16px', // Add padding for better spacing from card border\n }}\n >\n <Button\n variant=\"text\"\n startIcon={<FileDownloadOutlinedIcon />}\n onClick={debouncedHandleCSVDownload}\n sx={{\n color: theme.palette.primary.main,\n textTransform: 'none',\n fontSize: '1rem',\n fontWeight: 400,\n textDecoration: 'none',\n '&:hover': {\n backgroundColor: 'transparent',\n textDecoration: 'none',\n },\n }}\n >\n {loading ? t('common.downloading') : t('common.exportCSV')}\n </Button>\n </Box>\n );\n};\n\nexport default ExportCSVButton;\n"],"names":[],"mappings":";;;;;;;;;;;;AA4BA,MAAM,kBAAkB,MAAM;AAC5B,EAAA,MAAM,CAAC,OAAA,EAAS,UAAU,CAAA,GAAI,SAAS,KAAK,CAAA;AAC5C,EAAM,MAAA,GAAA,GAAM,OAAO,sBAAsB,CAAA;AACzC,EAAA,MAAM,EAAE,cAAA,EAAgB,YAAa,EAAA,GAAI,YAAa,EAAA;AACtD,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAC7B,EAAM,MAAA,WAAA,GAAc,OAA8B,IAAI,CAAA;AAEtD,EAAA,MAAM,oBAAoB,YAAY;AACpC,IAAI,IAAA;AACF,MAAA,MAAM,SAAY,GAAA,MAAA,iBAAW,IAAA,IAAA,IAAQ,yBAAyB,CAAA;AAC9D,MAAA,MAAM,IAAI,YAAa,CAAA;AAAA,QACrB,IAAM,EAAA,cAAA;AAAA,QACN,UAAY,EAAA,cAAA,GACR,MAAO,CAAA,cAAA,EAAgB,YAAY,CACnC,GAAA,KAAA,CAAA;AAAA,QACJ,QAAU,EAAA,YAAA,GAAe,MAAO,CAAA,YAAA,EAAc,YAAY,CAAI,GAAA,KAAA,CAAA;AAAA,QAC9D,UAAU,IAAI,IAAA,CAAK,cAAe,EAAA,CAAE,iBAAkB,CAAA,QAAA;AAAA,QACtD,MAAQ,EAAA,KAAA;AAAA,QACR,UAAU,CAAG,EAAA,CAAA,CAAE,oBAAoB,CAAC,IAAI,SAAS,CAAA,IAAA;AAAA,OAClD,CAAA;AAAA,aACM,KAAO,EAAA;AAEd,MAAQ,OAAA,CAAA,KAAA,CAAM,wBAAwB,KAAK,CAAA;AAAA,KAC3C,SAAA;AACA,MAAA,UAAA,CAAW,KAAK,CAAA;AAAA;AAClB,GACF;AAEA,EAAA,MAAM,6BAA6B,MAAM;AACvC,IAAA,UAAA,CAAW,IAAI,CAAA;AACf,IAAA,IAAI,YAAY,OAAS,EAAA;AACvB,MAAA,YAAA,CAAa,YAAY,OAAO,CAAA;AAAA;AAElC,IAAY,WAAA,CAAA,OAAA,GAAU,WAAW,MAAM;AACrC,MAAkB,iBAAA,EAAA;AAAA,OACjB,GAAG,CAAA;AAAA,GACR;AAEA,EACE,uBAAA,GAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,EAAI,EAAA;AAAA,QACF,MAAQ,EAAA,MAAA;AAAA,QACR,QAAU,EAAA,GAAA;AAAA,QACV,OAAS,EAAA,MAAA;AAAA,QACT,UAAY,EAAA,QAAA;AAAA,QACZ,cAAgB,EAAA,QAAA;AAAA,QAChB,OAAS,EAAA;AAAA;AAAA,OACX;AAAA,MAEA,QAAA,kBAAA,GAAA;AAAA,QAAC,MAAA;AAAA,QAAA;AAAA,UACC,OAAQ,EAAA,MAAA;AAAA,UACR,SAAA,sBAAY,wBAAyB,EAAA,EAAA,CAAA;AAAA,UACrC,OAAS,EAAA,0BAAA;AAAA,UACT,EAAI,EAAA;AAAA,YACF,KAAA,EAAO,KAAM,CAAA,OAAA,CAAQ,OAAQ,CAAA,IAAA;AAAA,YAC7B,aAAe,EAAA,MAAA;AAAA,YACf,QAAU,EAAA,MAAA;AAAA,YACV,UAAY,EAAA,GAAA;AAAA,YACZ,cAAgB,EAAA,MAAA;AAAA,YAChB,SAAW,EAAA;AAAA,cACT,eAAiB,EAAA,aAAA;AAAA,cACjB,cAAgB,EAAA;AAAA;AAClB,WACF;AAAA,UAEC,QAAU,EAAA,OAAA,GAAA,CAAA,CAAE,oBAAoB,CAAA,GAAI,EAAE,kBAAkB;AAAA;AAAA;AAC3D;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -14,16 +14,18 @@ import Users from '../Users/Users.esm.js';
|
|
|
14
14
|
import { DateRangeProvider } from '../Header/DateRangeContext.esm.js';
|
|
15
15
|
import { useAdoptionInsightsEventsReadPermission } from '../../hooks/useAdoptionInsightsEventsReadPermission.esm.js';
|
|
16
16
|
import PermissionRequiredState from '../Common/PermissionRequiredState.esm.js';
|
|
17
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
17
18
|
|
|
18
19
|
const AdoptionInsightsPage = () => {
|
|
19
20
|
const theme = useTheme();
|
|
20
21
|
const isSmallScreen = useMediaQuery(theme.breakpoints.down("sm"));
|
|
21
22
|
const { allowed: hasEventsReadPermission, loading } = useAdoptionInsightsEventsReadPermission();
|
|
23
|
+
const { t } = useTranslation();
|
|
22
24
|
if (loading) {
|
|
23
25
|
return null;
|
|
24
26
|
}
|
|
25
27
|
return /* @__PURE__ */ jsx(Page, { themeId: "home", children: !hasEventsReadPermission ? /* @__PURE__ */ jsx(Content, { children: /* @__PURE__ */ jsx(PermissionRequiredState, {}) }) : /* @__PURE__ */ jsxs(DateRangeProvider, { children: [
|
|
26
|
-
/* @__PURE__ */ jsx(InsightsHeader, { title: "
|
|
28
|
+
/* @__PURE__ */ jsx(InsightsHeader, { title: t("page.title") }),
|
|
27
29
|
/* @__PURE__ */ jsx(Content, { children: /* @__PURE__ */ jsxs(Masonry, { columns: isSmallScreen ? 1 : 2, spacing: 2, children: [
|
|
28
30
|
/* @__PURE__ */ jsx(ActiveUsers, {}),
|
|
29
31
|
/* @__PURE__ */ jsx(Users, {}),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AdoptionInsightsPage.esm.js","sources":["../../../src/components/AdoptionInsightsPage/AdoptionInsightsPage.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport { Content, Page } from '@backstage/core-components';\nimport Masonry from '@mui/lab/Masonry';\nimport useMediaQuery from '@mui/material/useMediaQuery';\nimport { useTheme } from '@mui/material/styles';\n\nimport InsightsHeader from '../Header';\nimport CatalogEntities from '../CatalogEntities';\nimport Templates from '../Templates';\nimport Techdocs from '../Techdocs';\nimport ActiveUsers from '../ActiveUsers';\nimport Plugins from '../Plugins';\nimport Searches from '../Searches';\nimport Users from '../Users';\nimport { DateRangeProvider } from '../Header/DateRangeContext';\nimport { useAdoptionInsightsEventsReadPermission } from '../../hooks/useAdoptionInsightsEventsReadPermission';\nimport PermissionRequiredState from '../Common/PermissionRequiredState';\n\nexport const AdoptionInsightsPage = () => {\n const theme = useTheme();\n const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));\n const { allowed: hasEventsReadPermission, loading } =\n useAdoptionInsightsEventsReadPermission();\n\n if (loading) {\n return null;\n }\n\n return (\n <Page themeId=\"home\">\n {!hasEventsReadPermission ? (\n <Content>\n <PermissionRequiredState />\n </Content>\n ) : (\n <DateRangeProvider>\n <InsightsHeader title
|
|
1
|
+
{"version":3,"file":"AdoptionInsightsPage.esm.js","sources":["../../../src/components/AdoptionInsightsPage/AdoptionInsightsPage.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport { Content, Page } from '@backstage/core-components';\nimport Masonry from '@mui/lab/Masonry';\nimport useMediaQuery from '@mui/material/useMediaQuery';\nimport { useTheme } from '@mui/material/styles';\n\nimport InsightsHeader from '../Header';\nimport CatalogEntities from '../CatalogEntities';\nimport Templates from '../Templates';\nimport Techdocs from '../Techdocs';\nimport ActiveUsers from '../ActiveUsers';\nimport Plugins from '../Plugins';\nimport Searches from '../Searches';\nimport Users from '../Users';\nimport { DateRangeProvider } from '../Header/DateRangeContext';\nimport { useAdoptionInsightsEventsReadPermission } from '../../hooks/useAdoptionInsightsEventsReadPermission';\nimport PermissionRequiredState from '../Common/PermissionRequiredState';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nexport const AdoptionInsightsPage = () => {\n const theme = useTheme();\n const isSmallScreen = useMediaQuery(theme.breakpoints.down('sm'));\n const { allowed: hasEventsReadPermission, loading } =\n useAdoptionInsightsEventsReadPermission();\n const { t } = useTranslation();\n\n if (loading) {\n return null;\n }\n\n return (\n <Page themeId=\"home\">\n {!hasEventsReadPermission ? (\n <Content>\n <PermissionRequiredState />\n </Content>\n ) : (\n <DateRangeProvider>\n <InsightsHeader title={t('page.title')} />\n <Content>\n <Masonry columns={isSmallScreen ? 1 : 2} spacing={2}>\n <ActiveUsers />\n <Users />\n <Templates />\n <CatalogEntities />\n <Plugins />\n <Techdocs />\n <Searches />\n </Masonry>\n </Content>\n </DateRangeProvider>\n )}\n </Page>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;AAiCO,MAAM,uBAAuB,MAAM;AACxC,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAA,MAAM,gBAAgB,aAAc,CAAA,KAAA,CAAM,WAAY,CAAA,IAAA,CAAK,IAAI,CAAC,CAAA;AAChE,EAAA,MAAM,EAAE,OAAA,EAAS,uBAAyB,EAAA,OAAA,KACxC,uCAAwC,EAAA;AAC1C,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAE7B,EAAA,IAAI,OAAS,EAAA;AACX,IAAO,OAAA,IAAA;AAAA;AAGT,EAAA,uBACG,GAAA,CAAA,IAAA,EAAA,EAAK,OAAQ,EAAA,MAAA,EACX,QAAC,EAAA,CAAA,uBAAA,mBACC,GAAA,CAAA,OAAA,EAAA,EACC,QAAC,kBAAA,GAAA,CAAA,uBAAA,EAAA,EAAwB,CAC3B,EAAA,CAAA,wBAEC,iBACC,EAAA,EAAA,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,cAAe,EAAA,EAAA,KAAA,EAAO,CAAE,CAAA,YAAY,CAAG,EAAA,CAAA;AAAA,oBACxC,GAAA,CAAC,WACC,QAAC,kBAAA,IAAA,CAAA,OAAA,EAAA,EAAQ,SAAS,aAAgB,GAAA,CAAA,GAAI,CAAG,EAAA,OAAA,EAAS,CAChD,EAAA,QAAA,EAAA;AAAA,sBAAA,GAAA,CAAC,WAAY,EAAA,EAAA,CAAA;AAAA,0BACZ,KAAM,EAAA,EAAA,CAAA;AAAA,0BACN,SAAU,EAAA,EAAA,CAAA;AAAA,0BACV,eAAgB,EAAA,EAAA,CAAA;AAAA,0BAChB,OAAQ,EAAA,EAAA,CAAA;AAAA,0BACR,QAAS,EAAA,EAAA,CAAA;AAAA,0BACT,QAAS,EAAA,EAAA;AAAA,KAAA,EACZ,CACF,EAAA;AAAA,GAAA,EACF,CAEJ,EAAA,CAAA;AAEJ;;;;"}
|
|
@@ -2,7 +2,38 @@ import { jsx } from 'react/jsx-runtime';
|
|
|
2
2
|
import Box from '@mui/material/Box';
|
|
3
3
|
import Paper from '@mui/material/Paper';
|
|
4
4
|
import TablePagination from '@mui/material/TablePagination';
|
|
5
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
5
6
|
|
|
7
|
+
const generateRowsPerPageOptions = (totalCount, t) => {
|
|
8
|
+
const defaultOptions = [3, 5, 10, 20];
|
|
9
|
+
const maxDefaultOption = Math.max(...defaultOptions);
|
|
10
|
+
if (defaultOptions.includes(totalCount)) {
|
|
11
|
+
const validOptions = defaultOptions.filter((option) => option <= totalCount);
|
|
12
|
+
return validOptions.map((value) => ({
|
|
13
|
+
label: t("table.pagination.topN", { count: value.toString() }),
|
|
14
|
+
value
|
|
15
|
+
}));
|
|
16
|
+
}
|
|
17
|
+
const validDefaults = defaultOptions.filter((option) => option < totalCount);
|
|
18
|
+
if (validDefaults.length > 0 && totalCount <= maxDefaultOption) {
|
|
19
|
+
const options = validDefaults.map((value) => ({
|
|
20
|
+
label: t("table.pagination.topN", { count: value.toString() }),
|
|
21
|
+
value
|
|
22
|
+
}));
|
|
23
|
+
options.push({
|
|
24
|
+
label: t("filter.all", {}),
|
|
25
|
+
value: totalCount
|
|
26
|
+
});
|
|
27
|
+
return options;
|
|
28
|
+
}
|
|
29
|
+
if (validDefaults.length > 0) {
|
|
30
|
+
return validDefaults.map((value) => ({
|
|
31
|
+
label: t("table.pagination.topN", { count: value.toString() }),
|
|
32
|
+
value
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
return [];
|
|
36
|
+
};
|
|
6
37
|
const TableFooterPagination = ({
|
|
7
38
|
count,
|
|
8
39
|
rowsPerPage,
|
|
@@ -10,6 +41,11 @@ const TableFooterPagination = ({
|
|
|
10
41
|
handleChangePage,
|
|
11
42
|
handleChangeRowsPerPage
|
|
12
43
|
}) => {
|
|
44
|
+
const { t } = useTranslation();
|
|
45
|
+
const rowsPerPageOptions = generateRowsPerPageOptions(count, t);
|
|
46
|
+
if (rowsPerPageOptions.length <= 1) {
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
13
49
|
return /* @__PURE__ */ jsx(
|
|
14
50
|
Box,
|
|
15
51
|
{
|
|
@@ -27,12 +63,7 @@ const TableFooterPagination = ({
|
|
|
27
63
|
backgroundColor: "transparent"
|
|
28
64
|
}
|
|
29
65
|
},
|
|
30
|
-
rowsPerPageOptions
|
|
31
|
-
{ label: "Top 3", value: 3 },
|
|
32
|
-
{ label: "Top 5", value: 5 },
|
|
33
|
-
{ label: "Top 10", value: 10 },
|
|
34
|
-
{ label: "Top 20", value: 20 }
|
|
35
|
-
],
|
|
66
|
+
rowsPerPageOptions,
|
|
36
67
|
component: "div",
|
|
37
68
|
count,
|
|
38
69
|
rowsPerPage,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TableFooterPagination.esm.js","sources":["../../../src/components/CardFooter/TableFooterPagination.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport type { MouseEvent, ChangeEvent, FC } from 'react';\nimport Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport TablePagination from '@mui/material/TablePagination';\n\ninterface TableFooterPaginationProps {\n count: number;\n rowsPerPage: number;\n page: number;\n handleChangePage: (\n event: MouseEvent<HTMLButtonElement> | null,\n newPage: number,\n ) => void;\n handleChangeRowsPerPage: (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,\n ) => void;\n}\n\nconst TableFooterPagination: FC<TableFooterPaginationProps> = ({\n count,\n rowsPerPage,\n page,\n handleChangePage,\n handleChangeRowsPerPage,\n}) => {\n return (\n <Box\n component={Paper}\n sx={{\n display: 'flex',\n justifyContent: 'flex-end',\n padding: 1,\n }}\n >\n <TablePagination\n sx={{\n '& .v5-MuiTablePagination-select:focus': {\n backgroundColor: 'transparent',\n },\n }}\n rowsPerPageOptions={
|
|
1
|
+
{"version":3,"file":"TableFooterPagination.esm.js","sources":["../../../src/components/CardFooter/TableFooterPagination.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport type { MouseEvent, ChangeEvent, FC } from 'react';\nimport Box from '@mui/material/Box';\nimport Paper from '@mui/material/Paper';\nimport TablePagination from '@mui/material/TablePagination';\n\nimport { useTranslation } from '../../hooks/useTranslation';\n\ninterface TableFooterPaginationProps {\n count: number;\n rowsPerPage: number;\n page: number;\n handleChangePage: (\n event: MouseEvent<HTMLButtonElement> | null,\n newPage: number,\n ) => void;\n handleChangeRowsPerPage: (\n event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>,\n ) => void;\n}\n\nconst generateRowsPerPageOptions = (totalCount: number, t: any) => {\n const defaultOptions = [3, 5, 10, 20];\n const maxDefaultOption = Math.max(...defaultOptions);\n\n if (defaultOptions.includes(totalCount)) {\n const validOptions = defaultOptions.filter(option => option <= totalCount);\n return validOptions.map(value => ({\n label: t('table.pagination.topN' as any, { count: value.toString() }),\n value,\n }));\n }\n\n const validDefaults = defaultOptions.filter(option => option < totalCount);\n\n if (validDefaults.length > 0 && totalCount <= maxDefaultOption) {\n const options = validDefaults.map(value => ({\n label: t('table.pagination.topN' as any, { count: value.toString() }),\n value,\n }));\n\n options.push({\n label: t('filter.all' as any, {}),\n value: totalCount,\n });\n\n return options;\n }\n\n if (validDefaults.length > 0) {\n return validDefaults.map(value => ({\n label: t('table.pagination.topN' as any, { count: value.toString() }),\n value,\n }));\n }\n\n return [];\n};\n\nconst TableFooterPagination: FC<TableFooterPaginationProps> = ({\n count,\n rowsPerPage,\n page,\n handleChangePage,\n handleChangeRowsPerPage,\n}) => {\n const { t } = useTranslation();\n const rowsPerPageOptions = generateRowsPerPageOptions(count, t);\n\n if (rowsPerPageOptions.length <= 1) {\n return null;\n }\n\n return (\n <Box\n component={Paper}\n sx={{\n display: 'flex',\n justifyContent: 'flex-end',\n padding: 1,\n }}\n >\n <TablePagination\n sx={{\n '& .v5-MuiTablePagination-select:focus': {\n backgroundColor: 'transparent',\n },\n }}\n rowsPerPageOptions={rowsPerPageOptions}\n component=\"div\"\n count={count}\n rowsPerPage={rowsPerPage}\n page={page}\n onPageChange={handleChangePage}\n onRowsPerPageChange={handleChangeRowsPerPage}\n labelRowsPerPage={null}\n labelDisplayedRows={() => null}\n ActionsComponent={() => null}\n slotProps={{\n select: {\n MenuProps: {\n MenuListProps: {\n autoFocusItem: false,\n },\n PaperProps: {\n sx: {\n width: 190,\n boxShadow: '0px 4px 10px rgba(0, 0, 0, 0.2)',\n borderRadius: 2,\n border: theme => `1px solid ${theme.palette.grey[300]}`,\n overflow: 'hidden',\n },\n },\n },\n },\n }}\n />\n </Box>\n );\n};\n\nexport default TableFooterPagination;\n"],"names":[],"mappings":"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"}
|
|
@@ -13,12 +13,13 @@ import Link from '@mui/material/Link';
|
|
|
13
13
|
import { entityRouteRef } from '@backstage/plugin-catalog-react';
|
|
14
14
|
import { useRouteRef } from '@backstage/core-plugin-api';
|
|
15
15
|
import CardWrapper from '../CardWrapper/CardWrapper.esm.js';
|
|
16
|
-
import {
|
|
16
|
+
import { CATALOG_ENTITIES_TABLE_HEADERS } from '../../utils/constants.esm.js';
|
|
17
17
|
import { useCatalogEntities } from '../../hooks/useCatalogEntities.esm.js';
|
|
18
18
|
import TableFooterPagination from '../CardFooter/TableFooterPagination.esm.js';
|
|
19
19
|
import { getUniqueCatalogEntityKinds, getLastUsedDay } from '../../utils/utils.esm.js';
|
|
20
20
|
import FilterDropdown from './FilterDropdown.esm.js';
|
|
21
21
|
import EmptyChartState from '../Common/EmptyChartState.esm.js';
|
|
22
|
+
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
22
23
|
|
|
23
24
|
const CatalogEntities = () => {
|
|
24
25
|
const [page, setPage] = useState(0);
|
|
@@ -26,6 +27,7 @@ const CatalogEntities = () => {
|
|
|
26
27
|
const [rowsPerPage, setRowsPerPage] = useState(3);
|
|
27
28
|
const [selectedOption, setSelectedOption] = useState("");
|
|
28
29
|
const [uniqueCatalogEntityKinds, setUniqueCatalogEntityKinds] = useState([]);
|
|
30
|
+
const { t } = useTranslation();
|
|
29
31
|
const entityLink = useRouteRef(entityRouteRef);
|
|
30
32
|
const { catalogEntities, loading, error } = useCatalogEntities({
|
|
31
33
|
limit,
|
|
@@ -59,16 +61,16 @@ const CatalogEntities = () => {
|
|
|
59
61
|
}).slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);
|
|
60
62
|
}, [catalogEntities, page, rowsPerPage, selectedOption]);
|
|
61
63
|
if (error) {
|
|
62
|
-
return /* @__PURE__ */ jsx(CardWrapper, { title:
|
|
64
|
+
return /* @__PURE__ */ jsx(CardWrapper, { title: t("catalogEntities.title"), children: /* @__PURE__ */ jsx(ResponseErrorPanel, { error }) });
|
|
63
65
|
}
|
|
64
66
|
if ((!visibleCatalogEntities || visibleCatalogEntities?.length === 0) && !loading) {
|
|
65
|
-
return /* @__PURE__ */ jsx(CardWrapper, { title:
|
|
67
|
+
return /* @__PURE__ */ jsx(CardWrapper, { title: t("catalogEntities.title"), children: /* @__PURE__ */ jsx(
|
|
66
68
|
Box,
|
|
67
69
|
{
|
|
68
70
|
display: "flex",
|
|
69
71
|
justifyContent: "center",
|
|
70
72
|
alignItems: "center",
|
|
71
|
-
|
|
73
|
+
minHeight: 80,
|
|
72
74
|
children: /* @__PURE__ */ jsx(EmptyChartState, {})
|
|
73
75
|
}
|
|
74
76
|
) });
|
|
@@ -76,7 +78,9 @@ const CatalogEntities = () => {
|
|
|
76
78
|
return /* @__PURE__ */ jsx(
|
|
77
79
|
CardWrapper,
|
|
78
80
|
{
|
|
79
|
-
title:
|
|
81
|
+
title: rowsPerPage >= (catalogEntities.data?.length ?? 0) ? t("catalogEntities.allTitle", {}) : t("catalogEntities.topNTitle", {
|
|
82
|
+
count: rowsPerPage.toString()
|
|
83
|
+
}),
|
|
80
84
|
filter: /* @__PURE__ */ jsx(
|
|
81
85
|
FilterDropdown,
|
|
82
86
|
{
|
|
@@ -94,7 +98,7 @@ const CatalogEntities = () => {
|
|
|
94
98
|
borderBottom: (theme) => `1px solid ${theme.palette.grey[300]}`,
|
|
95
99
|
width: "25%"
|
|
96
100
|
},
|
|
97
|
-
children: header.
|
|
101
|
+
children: t(header.titleKey, {})
|
|
98
102
|
},
|
|
99
103
|
header.id
|
|
100
104
|
)) }) }),
|
|
@@ -134,7 +138,7 @@ const CatalogEntities = () => {
|
|
|
134
138
|
}
|
|
135
139
|
) }),
|
|
136
140
|
/* @__PURE__ */ jsx(TableCell, { sx: { width: "25%" }, children: entity.kind?.charAt(0).toLocaleUpperCase("en-US") + entity.kind?.slice(1) || "--" }),
|
|
137
|
-
/* @__PURE__ */ jsx(TableCell, { sx: { width: "25%" }, children: getLastUsedDay(entity.last_used) ?? "--" }),
|
|
141
|
+
/* @__PURE__ */ jsx(TableCell, { sx: { width: "25%" }, children: getLastUsedDay(entity.last_used, t) ?? "--" }),
|
|
138
142
|
/* @__PURE__ */ jsx(TableCell, { sx: { width: "25%" }, children: Number(entity.count).toLocaleString("en-US") ?? "--" })
|
|
139
143
|
]
|
|
140
144
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CatalogEntities.esm.js","sources":["../../../src/components/CatalogEntities/CatalogEntities.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport { useState, useEffect, useMemo, useCallback } from 'react';\nimport type { ChangeEvent } from 'react';\n\nimport { ResponseErrorPanel } from '@backstage/core-components';\nimport Box from '@mui/material/Box';\nimport { SelectChangeEvent } from '@mui/material/Select';\nimport Table from '@mui/material/Table';\nimport TableBody from '@mui/material/TableBody';\nimport TableCell from '@mui/material/TableCell';\nimport TableFooter from '@mui/material/TableFooter';\nimport TableHead from '@mui/material/TableHead';\nimport TableRow from '@mui/material/TableRow';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Link from '@mui/material/Link';\nimport { entityRouteRef } from '@backstage/plugin-catalog-react';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport CardWrapper from '../CardWrapper';\nimport {\n CATALOG_ENTITIES_TABLE_HEADERS,\n CATALOG_ENTITIES_TITLE,\n} from '../../utils/constants';\nimport { useCatalogEntities } from '../../hooks/useCatalogEntities';\nimport TableFooterPagination from '../CardFooter';\nimport { getLastUsedDay, getUniqueCatalogEntityKinds } from '../../utils/utils';\nimport FilterDropdown from './FilterDropdown';\nimport EmptyChartState from '../Common/EmptyChartState';\n\nconst CatalogEntities = () => {\n const [page, setPage] = useState(0);\n const [limit] = useState(20);\n const [rowsPerPage, setRowsPerPage] = useState(3);\n const [selectedOption, setSelectedOption] = useState('');\n const [uniqueCatalogEntityKinds, setUniqueCatalogEntityKinds] = useState<\n string[]\n >([]);\n\n const entityLink = useRouteRef(entityRouteRef);\n\n const { catalogEntities, loading, error } = useCatalogEntities({\n limit,\n kind: selectedOption === 'All' ? '' : selectedOption.toLocaleLowerCase(),\n });\n\n useEffect(() => {\n if (\n catalogEntities?.data?.length > 0 &&\n uniqueCatalogEntityKinds?.length === 0\n ) {\n const uniqueKinds = getUniqueCatalogEntityKinds(catalogEntities.data);\n setUniqueCatalogEntityKinds(uniqueKinds);\n }\n }, [catalogEntities, uniqueCatalogEntityKinds]);\n\n const handleChangePage = useCallback((_event: unknown, newPage: number) => {\n setPage(newPage);\n }, []);\n\n const handleChangeRowsPerPage = useCallback(\n (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n setRowsPerPage(+event.target.value);\n setPage(0);\n },\n [],\n );\n\n const handleChange = useCallback((event: SelectChangeEvent<string>) => {\n setSelectedOption(event.target.value);\n }, []);\n\n const visibleCatalogEntities = useMemo(() => {\n return catalogEntities.data\n ?.filter(entity => {\n if (selectedOption && selectedOption !== 'All') {\n return (\n entity.kind.toLocaleLowerCase() ===\n selectedOption.toLocaleLowerCase()\n );\n }\n return true;\n })\n .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);\n }, [catalogEntities, page, rowsPerPage, selectedOption]);\n\n if (error) {\n return (\n <CardWrapper title={CATALOG_ENTITIES_TITLE}>\n <ResponseErrorPanel error={error} />\n </CardWrapper>\n );\n }\n\n if (\n (!visibleCatalogEntities || visibleCatalogEntities?.length === 0) &&\n !loading\n ) {\n return (\n <CardWrapper title={CATALOG_ENTITIES_TITLE}>\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n height={200}\n >\n <EmptyChartState />\n </Box>\n </CardWrapper>\n );\n }\n\n return (\n <CardWrapper\n title={CATALOG_ENTITIES_TITLE}\n filter={\n <FilterDropdown\n selectedOption={selectedOption}\n handleChange={handleChange}\n uniqueCatalogEntityKinds={uniqueCatalogEntityKinds}\n />\n }\n >\n <Table aria-labelledby=\"Catalog entities\" sx={{ width: '100%' }}>\n <TableHead>\n <TableRow>\n {CATALOG_ENTITIES_TABLE_HEADERS.map(header => (\n <TableCell\n key={header.id}\n align=\"left\"\n sx={{\n borderBottom: theme => `1px solid ${theme.palette.grey[300]}`,\n width: '25%',\n }}\n >\n {header.title}\n </TableCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n <TableRow>\n <TableCell\n colSpan={CATALOG_ENTITIES_TABLE_HEADERS.length}\n align=\"center\"\n >\n <CircularProgress />\n </TableCell>\n </TableRow>\n ) : (\n visibleCatalogEntities?.map(entity => (\n <TableRow\n key={`${entity.kind}-${entity.name}`}\n sx={{\n '&:nth-of-type(odd)': { backgroundColor: 'inherit' },\n borderBottom: theme => `1px solid ${theme.palette.grey[300]}`,\n }}\n >\n <TableCell sx={{ width: '25%' }}>\n <Link\n component=\"a\"\n href={entityLink({\n kind: entity.kind,\n namespace: entity.namespace,\n name: entity.name,\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n sx={{\n textDecoration: 'none',\n '&:hover': {\n textDecoration: 'none',\n },\n }}\n >\n {entity.name ?? '--'}\n </Link>\n </TableCell>\n <TableCell sx={{ width: '25%' }}>\n {entity.kind?.charAt(0).toLocaleUpperCase('en-US') +\n entity.kind?.slice(1) || '--'}\n </TableCell>\n <TableCell sx={{ width: '25%' }}>\n {getLastUsedDay(entity.last_used) ?? '--'}\n </TableCell>\n <TableCell sx={{ width: '25%' }}>\n {Number(entity.count).toLocaleString('en-US') ?? '--'}\n </TableCell>\n </TableRow>\n ))\n )}\n </TableBody>\n <TableFooter>\n <TableRow>\n <TableCell\n colSpan={CATALOG_ENTITIES_TABLE_HEADERS.length}\n sx={{ padding: 0 }}\n >\n <TableFooterPagination\n count={catalogEntities.data?.length}\n rowsPerPage={rowsPerPage}\n page={page}\n handleChangePage={handleChangePage}\n handleChangeRowsPerPage={handleChangeRowsPerPage}\n />\n </TableCell>\n </TableRow>\n </TableFooter>\n </Table>\n </CardWrapper>\n );\n};\n\nexport default CatalogEntities;\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CatalogEntities.esm.js","sources":["../../../src/components/CatalogEntities/CatalogEntities.tsx"],"sourcesContent":["/*\n * Copyright Red Hat, Inc.\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 */\nimport { useState, useEffect, useMemo, useCallback } from 'react';\nimport type { ChangeEvent } from 'react';\n\nimport { ResponseErrorPanel } from '@backstage/core-components';\nimport Box from '@mui/material/Box';\nimport { SelectChangeEvent } from '@mui/material/Select';\nimport Table from '@mui/material/Table';\nimport TableBody from '@mui/material/TableBody';\nimport TableCell from '@mui/material/TableCell';\nimport TableFooter from '@mui/material/TableFooter';\nimport TableHead from '@mui/material/TableHead';\nimport TableRow from '@mui/material/TableRow';\nimport CircularProgress from '@mui/material/CircularProgress';\nimport Link from '@mui/material/Link';\nimport { entityRouteRef } from '@backstage/plugin-catalog-react';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport CardWrapper from '../CardWrapper';\nimport { CATALOG_ENTITIES_TABLE_HEADERS } from '../../utils/constants';\nimport { useCatalogEntities } from '../../hooks/useCatalogEntities';\nimport TableFooterPagination from '../CardFooter';\nimport { getLastUsedDay, getUniqueCatalogEntityKinds } from '../../utils/utils';\nimport FilterDropdown from './FilterDropdown';\nimport EmptyChartState from '../Common/EmptyChartState';\nimport { useTranslation } from '../../hooks/useTranslation';\n\nconst CatalogEntities = () => {\n const [page, setPage] = useState(0);\n const [limit] = useState(20);\n const [rowsPerPage, setRowsPerPage] = useState(3);\n const [selectedOption, setSelectedOption] = useState('');\n const [uniqueCatalogEntityKinds, setUniqueCatalogEntityKinds] = useState<\n string[]\n >([]);\n const { t } = useTranslation();\n\n const entityLink = useRouteRef(entityRouteRef);\n\n const { catalogEntities, loading, error } = useCatalogEntities({\n limit,\n kind: selectedOption === 'All' ? '' : selectedOption.toLocaleLowerCase(),\n });\n\n useEffect(() => {\n if (\n catalogEntities?.data?.length > 0 &&\n uniqueCatalogEntityKinds?.length === 0\n ) {\n const uniqueKinds = getUniqueCatalogEntityKinds(catalogEntities.data);\n setUniqueCatalogEntityKinds(uniqueKinds);\n }\n }, [catalogEntities, uniqueCatalogEntityKinds]);\n\n const handleChangePage = useCallback((_event: unknown, newPage: number) => {\n setPage(newPage);\n }, []);\n\n const handleChangeRowsPerPage = useCallback(\n (event: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {\n setRowsPerPage(+event.target.value);\n setPage(0);\n },\n [],\n );\n\n const handleChange = useCallback((event: SelectChangeEvent<string>) => {\n setSelectedOption(event.target.value);\n }, []);\n\n const visibleCatalogEntities = useMemo(() => {\n return catalogEntities.data\n ?.filter(entity => {\n if (selectedOption && selectedOption !== 'All') {\n return (\n entity.kind.toLocaleLowerCase() ===\n selectedOption.toLocaleLowerCase()\n );\n }\n return true;\n })\n .slice(page * rowsPerPage, page * rowsPerPage + rowsPerPage);\n }, [catalogEntities, page, rowsPerPage, selectedOption]);\n\n if (error) {\n return (\n <CardWrapper title={t('catalogEntities.title')}>\n <ResponseErrorPanel error={error} />\n </CardWrapper>\n );\n }\n\n if (\n (!visibleCatalogEntities || visibleCatalogEntities?.length === 0) &&\n !loading\n ) {\n return (\n <CardWrapper title={t('catalogEntities.title')}>\n <Box\n display=\"flex\"\n justifyContent=\"center\"\n alignItems=\"center\"\n minHeight={80}\n >\n <EmptyChartState />\n </Box>\n </CardWrapper>\n );\n }\n\n return (\n <CardWrapper\n title={\n rowsPerPage >= (catalogEntities.data?.length ?? 0)\n ? t('catalogEntities.allTitle' as any, {})\n : t('catalogEntities.topNTitle' as any, {\n count: rowsPerPage.toString(),\n })\n }\n filter={\n <FilterDropdown\n selectedOption={selectedOption}\n handleChange={handleChange}\n uniqueCatalogEntityKinds={uniqueCatalogEntityKinds}\n />\n }\n >\n <Table aria-labelledby=\"Catalog entities\" sx={{ width: '100%' }}>\n <TableHead>\n <TableRow>\n {CATALOG_ENTITIES_TABLE_HEADERS.map(header => (\n <TableCell\n key={header.id}\n align=\"left\"\n sx={{\n borderBottom: theme => `1px solid ${theme.palette.grey[300]}`,\n width: '25%',\n }}\n >\n {t(header.titleKey as any, {})}\n </TableCell>\n ))}\n </TableRow>\n </TableHead>\n <TableBody>\n {loading ? (\n <TableRow>\n <TableCell\n colSpan={CATALOG_ENTITIES_TABLE_HEADERS.length}\n align=\"center\"\n >\n <CircularProgress />\n </TableCell>\n </TableRow>\n ) : (\n visibleCatalogEntities?.map(entity => (\n <TableRow\n key={`${entity.kind}-${entity.name}`}\n sx={{\n '&:nth-of-type(odd)': { backgroundColor: 'inherit' },\n borderBottom: theme => `1px solid ${theme.palette.grey[300]}`,\n }}\n >\n <TableCell sx={{ width: '25%' }}>\n <Link\n component=\"a\"\n href={entityLink({\n kind: entity.kind,\n namespace: entity.namespace,\n name: entity.name,\n })}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n sx={{\n textDecoration: 'none',\n '&:hover': {\n textDecoration: 'none',\n },\n }}\n >\n {entity.name ?? '--'}\n </Link>\n </TableCell>\n <TableCell sx={{ width: '25%' }}>\n {entity.kind?.charAt(0).toLocaleUpperCase('en-US') +\n entity.kind?.slice(1) || '--'}\n </TableCell>\n <TableCell sx={{ width: '25%' }}>\n {getLastUsedDay(entity.last_used, t) ?? '--'}\n </TableCell>\n <TableCell sx={{ width: '25%' }}>\n {Number(entity.count).toLocaleString('en-US') ?? '--'}\n </TableCell>\n </TableRow>\n ))\n )}\n </TableBody>\n <TableFooter>\n <TableRow>\n <TableCell\n colSpan={CATALOG_ENTITIES_TABLE_HEADERS.length}\n sx={{ padding: 0 }}\n >\n <TableFooterPagination\n count={catalogEntities.data?.length}\n rowsPerPage={rowsPerPage}\n page={page}\n handleChangePage={handleChangePage}\n handleChangeRowsPerPage={handleChangeRowsPerPage}\n />\n </TableCell>\n </TableRow>\n </TableFooter>\n </Table>\n </CardWrapper>\n );\n};\n\nexport default CatalogEntities;\n"],"names":[],"mappings":"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"}
|