@red-hat-developer-hub/backstage-plugin-adoption-insights 0.1.0 → 0.2.1
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 +27 -0
- package/dist/api/index.esm.js +1 -1
- package/dist/api/index.esm.js.map +1 -1
- package/dist/components/ActiveUsers/ActiveUsers.esm.js +108 -90
- package/dist/components/ActiveUsers/ActiveUsers.esm.js.map +1 -1
- package/dist/components/ActiveUsers/CustomLegend.esm.js +40 -35
- package/dist/components/ActiveUsers/CustomLegend.esm.js.map +1 -1
- package/dist/components/ActiveUsers/ExportCSVButton.esm.js +27 -25
- package/dist/components/ActiveUsers/ExportCSVButton.esm.js.map +1 -1
- package/dist/components/AdoptionInsightsPage/AdoptionInsightsPage.esm.js +13 -2
- package/dist/components/AdoptionInsightsPage/AdoptionInsightsPage.esm.js.map +1 -1
- package/dist/components/CardFooter/TableFooterPagination.esm.js +42 -42
- package/dist/components/CardFooter/TableFooterPagination.esm.js.map +1 -1
- package/dist/components/CardWrapper/CardWrapper.esm.js +29 -24
- package/dist/components/CardWrapper/CardWrapper.esm.js.map +1 -1
- package/dist/components/CatalogEntities/CatalogEntities.esm.js +96 -92
- package/dist/components/CatalogEntities/CatalogEntities.esm.js.map +1 -1
- package/dist/components/CatalogEntities/FilterDropdown.esm.js +22 -17
- package/dist/components/CatalogEntities/FilterDropdown.esm.js.map +1 -1
- package/dist/components/Common/ChartTooltip.esm.js +91 -0
- package/dist/components/Common/ChartTooltip.esm.js.map +1 -0
- package/dist/components/Common/CustomCursor.esm.js +2 -2
- package/dist/components/Common/CustomCursor.esm.js.map +1 -1
- package/dist/components/Common/EmptyChartState.esm.js +2 -2
- package/dist/components/Common/EmptyChartState.esm.js.map +1 -1
- package/dist/components/Common/PermissionRequiredIcon.esm.js +2 -2
- package/dist/components/Common/PermissionRequiredIcon.esm.js.map +1 -1
- package/dist/components/Common/PermissionRequiredState.esm.js +29 -23
- package/dist/components/Common/PermissionRequiredState.esm.js.map +1 -1
- package/dist/components/Header/DateRangeContext.esm.js +7 -6
- package/dist/components/Header/DateRangeContext.esm.js.map +1 -1
- package/dist/components/Header/DateRangePicker.esm.js +67 -59
- package/dist/components/Header/DateRangePicker.esm.js.map +1 -1
- package/dist/components/Header/Header.esm.js +117 -106
- package/dist/components/Header/Header.esm.js.map +1 -1
- package/dist/components/Plugins/Plugins.esm.js +74 -64
- package/dist/components/Plugins/Plugins.esm.js.map +1 -1
- package/dist/components/Searches/Searches.esm.js +86 -75
- package/dist/components/Searches/Searches.esm.js.map +1 -1
- package/dist/components/Techdocs/Techdocs.esm.js +85 -81
- package/dist/components/Techdocs/Techdocs.esm.js.map +1 -1
- package/dist/components/Templates/Templates.esm.js +74 -70
- package/dist/components/Templates/Templates.esm.js.map +1 -1
- package/dist/components/Users/Info.esm.js +12 -12
- package/dist/components/Users/Info.esm.js.map +1 -1
- package/dist/components/Users/Tooltip.esm.js +27 -23
- package/dist/components/Users/Tooltip.esm.js.map +1 -1
- package/dist/components/Users/Users.esm.js +119 -95
- package/dist/components/Users/Users.esm.js.map +1 -1
- package/dist/hooks/useActiveUsers.esm.js +10 -8
- package/dist/hooks/useActiveUsers.esm.js.map +1 -1
- package/dist/hooks/useCatalogEntities.esm.js +9 -6
- package/dist/hooks/useCatalogEntities.esm.js.map +1 -1
- package/dist/hooks/usePlugins.esm.js +9 -6
- package/dist/hooks/usePlugins.esm.js.map +1 -1
- package/dist/hooks/useSearches.esm.js +11 -7
- package/dist/hooks/useSearches.esm.js.map +1 -1
- package/dist/hooks/useTechdocs.esm.js +9 -6
- package/dist/hooks/useTechdocs.esm.js.map +1 -1
- package/dist/hooks/useTemplates.esm.js +9 -6
- package/dist/hooks/useTemplates.esm.js.map +1 -1
- package/dist/hooks/useUsers.esm.js +10 -7
- package/dist/hooks/useUsers.esm.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/utils/utils.esm.js +70 -30
- package/dist/utils/utils.esm.js.map +1 -1
- package/package.json +19 -17
- package/dist/components/ActiveUsers/CustomTooltip.esm.js +0 -87
- package/dist/components/ActiveUsers/CustomTooltip.esm.js.map +0 -1
- package/dist/components/Searches/CustomTooltip.esm.js +0 -66
- package/dist/components/Searches/CustomTooltip.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
# @red-hat-developer-hub/backstage-plugin-adoption-insights
|
2
2
|
|
3
|
+
## 0.2.1
|
4
|
+
|
5
|
+
### Patch Changes
|
6
|
+
|
7
|
+
- 38372b3: Updated dependency `@red-hat-developer-hub/backstage-plugin-theme` to `^0.9.0`.
|
8
|
+
- 586901c: Timezone Fixes for Consistent Data Grouping and Display
|
9
|
+
|
10
|
+
- Backend now accepts an explicit timezone parameter from the frontend instead of relying on Intl.DateTimeFormat().resolvedOptions().timeZone.
|
11
|
+
- This eliminates discrepancies between frontend simulation and backend processing.
|
12
|
+
- Accurate Date Range Construction
|
13
|
+
- Updated PostgreSQL query to respect user timezone.
|
14
|
+
- Tooltips now show formatted times based on user's selected timeszone.
|
15
|
+
|
16
|
+
## 0.2.0
|
17
|
+
|
18
|
+
### Minor Changes
|
19
|
+
|
20
|
+
- 3a80c30: Backstage version bump to v1.39.1
|
21
|
+
|
22
|
+
### Patch Changes
|
23
|
+
|
24
|
+
- 3f93232: Updated dependency `@mui/icons-material` to `5.17.1`.
|
25
|
+
Updated dependency `@mui/material` to `5.17.1`.
|
26
|
+
Updated dependency `@red-hat-developer-hub/backstage-plugin-theme` to `^0.8.0`.
|
27
|
+
- Updated dependencies [3a80c30]
|
28
|
+
- @red-hat-developer-hub/backstage-plugin-adoption-insights-common@0.3.0
|
29
|
+
|
3
30
|
## 0.1.0
|
4
31
|
|
5
32
|
### Minor Changes
|
package/dist/api/index.esm.js
CHANGED
@@ -103,7 +103,7 @@ class AdoptionInsightsApiClient {
|
|
103
103
|
async downloadBlob(options) {
|
104
104
|
const baseUrl = await this.getBaseUrl();
|
105
105
|
const response = await this.fetchApi.fetch(
|
106
|
-
`${baseUrl}/events?type=${options.type}&start_date=${options.start_date}&end_date=${options.end_date}&format=${options.format}`
|
106
|
+
`${baseUrl}/events?type=${options.type}&start_date=${options.start_date}&end_date=${options.end_date}&format=${options.format}&timezone=${options.timezone}`
|
107
107
|
);
|
108
108
|
const blob = await response.blob();
|
109
109
|
const blobUrl = window.URL.createObjectURL(blob);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"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 { createApiRef, ConfigApi, FetchApi } from '@backstage/core-plugin-api';\nimport {\n AdoptionInsightsApi,\n APIsViewOptions,\n TemplatesResponse,\n CatalogEntitiesResponse,\n PluginTrendResponse,\n UsersResponse,\n TechdocsResponse,\n ActiveUsersResponse,\n SearchesResponse,\n} from '../types';\nimport { generateEventsUrl } from '../utils/utils';\n\nexport interface InsightsApi {\n downloadBlob(options: APIsViewOptions): Promise<any>;\n getActiveUsers(options: APIsViewOptions): Promise<ActiveUsersResponse>;\n getUsers(options: APIsViewOptions): Promise<UsersResponse>;\n getCatalogEntities(\n options: APIsViewOptions,\n ): Promise<CatalogEntitiesResponse>;\n getTemplates(options: APIsViewOptions): Promise<TemplatesResponse>;\n getTechdocs(options: APIsViewOptions): Promise<TechdocsResponse>;\n getPlugins(options: APIsViewOptions): Promise<PluginTrendResponse>;\n getSearches(options: APIsViewOptions): Promise<SearchesResponse>;\n}\n\nexport const adoptionInsightsApiRef = createApiRef<AdoptionInsightsApi>({\n id: 'plugin.adoption-insights.service',\n});\n\nexport type Options = {\n configApi: ConfigApi;\n fetchApi: FetchApi;\n};\n\nconst validateResponse = (response: Response, action: string) => {\n if (!response.body || !response.ok) {\n throw new Error(\n `failed to fetch ${action}, status ${response.status}: ${\n !response.ok ? response.statusText : 'Something went wrong.'\n }`,\n );\n }\n};\n\nexport class AdoptionInsightsApiClient implements AdoptionInsightsApi {\n private readonly configApi: ConfigApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: Options) {\n this.configApi = options.configApi;\n this.fetchApi = options.fetchApi;\n }\n\n async getBaseUrl() {\n return `${this.configApi.getString(\n 'backend.baseUrl',\n )}/api/adoption-insights`;\n }\n\n async getActiveUsers(options: APIsViewOptions): Promise<ActiveUsersResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ grouping: undefined, data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'active users');\n\n const data = await response.json();\n return data as ActiveUsersResponse;\n }\n\n async getUsers(options: APIsViewOptions): Promise<UsersResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'users');\n\n const data = await response.json();\n return data as UsersResponse;\n }\n\n async getCatalogEntities(\n options: APIsViewOptions,\n ): Promise<CatalogEntitiesResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'catalog entities');\n\n const data = await response.json();\n return data as CatalogEntitiesResponse;\n }\n\n async getTemplates(options: APIsViewOptions): Promise<TemplatesResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'templates');\n\n const data = await response.json();\n return data as TemplatesResponse;\n }\n\n async getTechdocs(options: APIsViewOptions): Promise<TechdocsResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'techdocs');\n\n const data = await response.json();\n return data as TechdocsResponse;\n }\n\n async getPlugins(options: APIsViewOptions): Promise<PluginTrendResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'plugins');\n\n const data = await response.json();\n return data as PluginTrendResponse;\n }\n\n async getSearches(options: APIsViewOptions): Promise<SearchesResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ grouping: undefined, data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'searches');\n\n const data = await response.json();\n return data as SearchesResponse;\n }\n\n async downloadBlob(options: APIsViewOptions): Promise<void> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/events?type=${options.type}&start_date=${options.start_date}&end_date=${options.end_date}&format=${options.format}`,\n );\n const blob = await response.blob();\n const blobUrl = window.URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = blobUrl;\n link.download = options.blobName ?? 'active-users';\n document.body.appendChild(link);\n link.click();\n link.parentNode?.removeChild(link);\n }\n}\n"],"names":[],"mappings":"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"}
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../src/api/index.ts"],"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 { createApiRef, ConfigApi, FetchApi } from '@backstage/core-plugin-api';\nimport {\n AdoptionInsightsApi,\n APIsViewOptions,\n TemplatesResponse,\n CatalogEntitiesResponse,\n PluginTrendResponse,\n UsersResponse,\n TechdocsResponse,\n ActiveUsersResponse,\n SearchesResponse,\n} from '../types';\nimport { generateEventsUrl } from '../utils/utils';\n\nexport interface InsightsApi {\n downloadBlob(options: APIsViewOptions): Promise<any>;\n getActiveUsers(options: APIsViewOptions): Promise<ActiveUsersResponse>;\n getUsers(options: APIsViewOptions): Promise<UsersResponse>;\n getCatalogEntities(\n options: APIsViewOptions,\n ): Promise<CatalogEntitiesResponse>;\n getTemplates(options: APIsViewOptions): Promise<TemplatesResponse>;\n getTechdocs(options: APIsViewOptions): Promise<TechdocsResponse>;\n getPlugins(options: APIsViewOptions): Promise<PluginTrendResponse>;\n getSearches(options: APIsViewOptions): Promise<SearchesResponse>;\n}\n\nexport const adoptionInsightsApiRef = createApiRef<AdoptionInsightsApi>({\n id: 'plugin.adoption-insights.service',\n});\n\nexport type Options = {\n configApi: ConfigApi;\n fetchApi: FetchApi;\n};\n\nconst validateResponse = (response: Response, action: string) => {\n if (!response.body || !response.ok) {\n throw new Error(\n `failed to fetch ${action}, status ${response.status}: ${\n !response.ok ? response.statusText : 'Something went wrong.'\n }`,\n );\n }\n};\n\nexport class AdoptionInsightsApiClient implements AdoptionInsightsApi {\n private readonly configApi: ConfigApi;\n private readonly fetchApi: FetchApi;\n\n constructor(options: Options) {\n this.configApi = options.configApi;\n this.fetchApi = options.fetchApi;\n }\n\n async getBaseUrl() {\n return `${this.configApi.getString(\n 'backend.baseUrl',\n )}/api/adoption-insights`;\n }\n\n async getActiveUsers(options: APIsViewOptions): Promise<ActiveUsersResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ grouping: undefined, data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'active users');\n\n const data = await response.json();\n return data as ActiveUsersResponse;\n }\n\n async getUsers(options: APIsViewOptions): Promise<UsersResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'users');\n\n const data = await response.json();\n return data as UsersResponse;\n }\n\n async getCatalogEntities(\n options: APIsViewOptions,\n ): Promise<CatalogEntitiesResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'catalog entities');\n\n const data = await response.json();\n return data as CatalogEntitiesResponse;\n }\n\n async getTemplates(options: APIsViewOptions): Promise<TemplatesResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'templates');\n\n const data = await response.json();\n return data as TemplatesResponse;\n }\n\n async getTechdocs(options: APIsViewOptions): Promise<TechdocsResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'techdocs');\n\n const data = await response.json();\n return data as TechdocsResponse;\n }\n\n async getPlugins(options: APIsViewOptions): Promise<PluginTrendResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'plugins');\n\n const data = await response.json();\n return data as PluginTrendResponse;\n }\n\n async getSearches(options: APIsViewOptions): Promise<SearchesResponse> {\n if (!options.start_date || !options.end_date) {\n return Promise.resolve({ grouping: undefined, data: [] });\n }\n\n const baseUrl = await this.getBaseUrl();\n const url = generateEventsUrl(`${baseUrl}/events`, options);\n\n const response = await this.fetchApi.fetch(url);\n\n validateResponse(response, 'searches');\n\n const data = await response.json();\n return data as SearchesResponse;\n }\n\n async downloadBlob(options: APIsViewOptions): Promise<void> {\n const baseUrl = await this.getBaseUrl();\n const response = await this.fetchApi.fetch(\n `${baseUrl}/events?type=${options.type}&start_date=${options.start_date}&end_date=${options.end_date}&format=${options.format}&timezone=${options.timezone}`,\n );\n const blob = await response.blob();\n const blobUrl = window.URL.createObjectURL(blob);\n const link = document.createElement('a');\n link.href = blobUrl;\n link.download = options.blobName ?? 'active-users';\n document.body.appendChild(link);\n link.click();\n link.parentNode?.removeChild(link);\n }\n}\n"],"names":[],"mappings":"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"}
|
@@ -1,11 +1,10 @@
|
|
1
|
-
import
|
1
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
2
2
|
import { ResponseErrorPanel } from '@backstage/core-components';
|
3
3
|
import Box from '@mui/material/Box';
|
4
4
|
import { useTheme } from '@mui/material/styles';
|
5
5
|
import CircularProgress from '@mui/material/CircularProgress';
|
6
6
|
import { ResponsiveContainer, AreaChart, CartesianGrid, XAxis, YAxis, Tooltip, Area, Legend } from 'recharts';
|
7
7
|
import CardWrapper from '../CardWrapper/CardWrapper.esm.js';
|
8
|
-
import CustomTooltip from './CustomTooltip.esm.js';
|
9
8
|
import CustomCursor from '../Common/CustomCursor.esm.js';
|
10
9
|
import CustomLegend from './CustomLegend.esm.js';
|
11
10
|
import { getAverage, getXAxisTickValues, getXAxisformat } from '../../utils/utils.esm.js';
|
@@ -13,6 +12,7 @@ import { useActiveUsers } from '../../hooks/useActiveUsers.esm.js';
|
|
13
12
|
import { Typography } from '@material-ui/core';
|
14
13
|
import ExportCSVButton from './ExportCSVButton.esm.js';
|
15
14
|
import EmptyChartState from '../Common/EmptyChartState.esm.js';
|
15
|
+
import ChartTooltip from '../Common/ChartTooltip.esm.js';
|
16
16
|
|
17
17
|
const ActiveUsers = () => {
|
18
18
|
const theme = useTheme();
|
@@ -20,109 +20,127 @@ const ActiveUsers = () => {
|
|
20
20
|
const { activeUsers, loading, error } = useActiveUsers();
|
21
21
|
const { data, grouping = "daily" } = activeUsers;
|
22
22
|
if (error) {
|
23
|
-
return /* @__PURE__ */
|
23
|
+
return /* @__PURE__ */ jsx(CardWrapper, { title: "Active users", children: /* @__PURE__ */ jsx(ResponseErrorPanel, { error }) });
|
24
24
|
}
|
25
25
|
if (!data || data?.length === 0 || !data?.[0] && !loading) {
|
26
|
-
return /* @__PURE__ */
|
26
|
+
return /* @__PURE__ */ jsx(CardWrapper, { title: "Active users", children: /* @__PURE__ */ jsx(
|
27
27
|
Box,
|
28
28
|
{
|
29
29
|
display: "flex",
|
30
30
|
justifyContent: "center",
|
31
31
|
alignItems: "center",
|
32
|
-
height: 200
|
33
|
-
|
34
|
-
|
35
|
-
));
|
32
|
+
height: 200,
|
33
|
+
children: /* @__PURE__ */ jsx(EmptyChartState, {})
|
34
|
+
}
|
35
|
+
) });
|
36
36
|
}
|
37
|
-
return /* @__PURE__ */
|
37
|
+
return /* @__PURE__ */ jsx(CardWrapper, { title: "Active users", filter: /* @__PURE__ */ jsx(ExportCSVButton, {}), children: loading ? /* @__PURE__ */ jsx(
|
38
38
|
Box,
|
39
39
|
{
|
40
40
|
display: "flex",
|
41
41
|
justifyContent: "center",
|
42
42
|
alignItems: "center",
|
43
|
-
height: 200
|
44
|
-
|
45
|
-
|
46
|
-
) : /* @__PURE__ */
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
},
|
54
|
-
/* @__PURE__ */
|
55
|
-
|
43
|
+
height: 200,
|
44
|
+
children: /* @__PURE__ */ jsx(CircularProgress, {})
|
45
|
+
}
|
46
|
+
) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
47
|
+
/* @__PURE__ */ jsxs(Typography, { style: { margin: "20px 36px" }, children: [
|
48
|
+
/* @__PURE__ */ jsx("b", { children: `${Math.round(getAverage(data, "total_users")).toLocaleString(
|
49
|
+
"en-Us"
|
50
|
+
)} active users per ${grouping === "hourly" ? "hour" : "day"}` }),
|
51
|
+
" ",
|
52
|
+
"were conducted during this period."
|
53
|
+
] }),
|
54
|
+
/* @__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
|
+
AreaChart,
|
56
56
|
{
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
57
|
+
data,
|
58
|
+
margin: { top: 10, right: 50, left: 20, bottom: 0 },
|
59
|
+
children: [
|
60
|
+
/* @__PURE__ */ jsxs("defs", { children: [
|
61
|
+
/* @__PURE__ */ jsxs("linearGradient", { id: "new_users", x1: "0", y1: "0", x2: "0", y2: "1", children: [
|
62
|
+
/* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: "#1976d2", stopOpacity: 0.8 }),
|
63
|
+
/* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: "#1976d2", stopOpacity: 0.2 })
|
64
|
+
] }),
|
65
|
+
/* @__PURE__ */ jsxs(
|
66
|
+
"linearGradient",
|
67
|
+
{
|
68
|
+
id: "returning_users",
|
69
|
+
x1: "0",
|
70
|
+
y1: "0",
|
71
|
+
x2: "0",
|
72
|
+
y2: "1",
|
73
|
+
children: [
|
74
|
+
/* @__PURE__ */ jsx("stop", { offset: "5%", stopColor: "#B8BBBE", stopOpacity: 0.8 }),
|
75
|
+
/* @__PURE__ */ jsx("stop", { offset: "95%", stopColor: "#B8BBBE", stopOpacity: 0.2 })
|
76
|
+
]
|
77
|
+
}
|
78
|
+
)
|
79
|
+
] }),
|
80
|
+
/* @__PURE__ */ jsx(
|
81
|
+
CartesianGrid,
|
82
|
+
{
|
83
|
+
stroke: isDarkMode ? "#666" : "#E5E7EB",
|
84
|
+
strokeDasharray: 0,
|
85
|
+
vertical: false
|
86
|
+
}
|
87
|
+
),
|
88
|
+
/* @__PURE__ */ jsx(
|
89
|
+
XAxis,
|
90
|
+
{
|
91
|
+
dataKey: "date",
|
92
|
+
tickFormatter: (date) => getXAxisformat(date, grouping),
|
93
|
+
ticks: getXAxisTickValues(data, grouping),
|
94
|
+
tick: { fill: theme.palette.text.primary },
|
95
|
+
axisLine: false,
|
96
|
+
tickLine: false,
|
97
|
+
padding: { left: 30, right: 30 },
|
98
|
+
tickMargin: 10
|
99
|
+
}
|
100
|
+
),
|
101
|
+
/* @__PURE__ */ jsx(
|
102
|
+
YAxis,
|
103
|
+
{
|
104
|
+
tick: { fill: theme.palette.text.primary },
|
105
|
+
tickLine: false,
|
106
|
+
axisLine: false,
|
107
|
+
tickFormatter: (value) => value.toLocaleString("en-Us"),
|
108
|
+
tickMargin: 20
|
109
|
+
}
|
110
|
+
),
|
111
|
+
/* @__PURE__ */ jsx(
|
112
|
+
Tooltip,
|
113
|
+
{
|
114
|
+
cursor: /* @__PURE__ */ jsx(CustomCursor, { cursorHeight: 250 }),
|
115
|
+
content: /* @__PURE__ */ jsx(ChartTooltip, { grouping })
|
116
|
+
}
|
117
|
+
),
|
118
|
+
/* @__PURE__ */ jsx(
|
119
|
+
Area,
|
120
|
+
{
|
121
|
+
type: "linear",
|
122
|
+
dataKey: "returning_users",
|
123
|
+
stroke: "#555",
|
124
|
+
fill: "url(#returning_users)",
|
125
|
+
strokeWidth: 1
|
126
|
+
}
|
127
|
+
),
|
128
|
+
/* @__PURE__ */ jsx(
|
129
|
+
Area,
|
130
|
+
{
|
131
|
+
type: "linear",
|
132
|
+
dataKey: "new_users",
|
133
|
+
stroke: "#1976d2",
|
134
|
+
fill: "url(#new_users)",
|
135
|
+
strokeWidth: 1
|
136
|
+
}
|
137
|
+
),
|
138
|
+
/* @__PURE__ */ jsx(Legend, { content: /* @__PURE__ */ jsx(CustomLegend, {}) })
|
139
|
+
]
|
62
140
|
},
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
/* @__PURE__ */ React__default.createElement(
|
67
|
-
CartesianGrid,
|
68
|
-
{
|
69
|
-
stroke: isDarkMode ? "#666" : "#E5E7EB",
|
70
|
-
strokeDasharray: 0,
|
71
|
-
vertical: false
|
72
|
-
}
|
73
|
-
),
|
74
|
-
/* @__PURE__ */ React__default.createElement(
|
75
|
-
XAxis,
|
76
|
-
{
|
77
|
-
dataKey: "date",
|
78
|
-
tickFormatter: (date) => getXAxisformat(date, grouping),
|
79
|
-
ticks: getXAxisTickValues(data, grouping),
|
80
|
-
tick: { fill: theme.palette.text.primary },
|
81
|
-
axisLine: false,
|
82
|
-
tickLine: false,
|
83
|
-
padding: { left: 30, right: 30 },
|
84
|
-
tickMargin: 10
|
85
|
-
}
|
86
|
-
),
|
87
|
-
/* @__PURE__ */ React__default.createElement(
|
88
|
-
YAxis,
|
89
|
-
{
|
90
|
-
tick: { fill: theme.palette.text.primary },
|
91
|
-
tickLine: false,
|
92
|
-
axisLine: false,
|
93
|
-
tickFormatter: (value) => value.toLocaleString(),
|
94
|
-
tickMargin: 20
|
95
|
-
}
|
96
|
-
),
|
97
|
-
/* @__PURE__ */ React__default.createElement(
|
98
|
-
Tooltip,
|
99
|
-
{
|
100
|
-
cursor: /* @__PURE__ */ React__default.createElement(CustomCursor, { cursorHeight: 250 }),
|
101
|
-
content: /* @__PURE__ */ React__default.createElement(CustomTooltip, { grouping })
|
102
|
-
}
|
103
|
-
),
|
104
|
-
/* @__PURE__ */ React__default.createElement(
|
105
|
-
Area,
|
106
|
-
{
|
107
|
-
type: "linear",
|
108
|
-
dataKey: "returning_users",
|
109
|
-
stroke: "#555",
|
110
|
-
fill: "url(#returning_users)",
|
111
|
-
strokeWidth: 1
|
112
|
-
}
|
113
|
-
),
|
114
|
-
/* @__PURE__ */ React__default.createElement(
|
115
|
-
Area,
|
116
|
-
{
|
117
|
-
type: "linear",
|
118
|
-
dataKey: "new_users",
|
119
|
-
stroke: "#1976d2",
|
120
|
-
fill: "url(#new_users)",
|
121
|
-
strokeWidth: 1
|
122
|
-
}
|
123
|
-
),
|
124
|
-
/* @__PURE__ */ React__default.createElement(Legend, { content: /* @__PURE__ */ React__default.createElement(CustomLegend, null) })
|
125
|
-
)))));
|
141
|
+
JSON.stringify(data.map((d) => d))
|
142
|
+
) }) })
|
143
|
+
] }) });
|
126
144
|
};
|
127
145
|
|
128
146
|
export { ActiveUsers as default };
|
@@ -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 React from 'react';\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 CustomTooltip from './CustomTooltip';\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';\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\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(\n getAverage(data, 'total_users'),\n ).toLocaleString()} active users per ${\n grouping === 'hourly' ? 'hour' : 'day'\n }`}\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 >\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()}\n tickMargin={20}\n />\n <Tooltip\n cursor={<CustomCursor cursorHeight={250} />}\n content={<CustomTooltip 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":["React"],"mappings":";;;;;;;;;;;;;;;;AA8CA,MAAM,cAAc,MAAM;AACxB,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAM,MAAA,UAAA,GAAa,KAAM,CAAA,OAAA,CAAQ,IAAS,KAAA,MAAA;AAE1C,EAAA,MAAM,EAAE,WAAA,EAAa,OAAS,EAAA,KAAA,KAAU,cAAe,EAAA;AACvD,EAAA,MAAM,EAAE,IAAA,EAAM,QAAW,GAAA,OAAA,EAAY,GAAA,WAAA;AAErC,EAAA,IAAI,KAAO,EAAA;AACT,IAAA,oDACG,WAAY,EAAA,EAAA,KAAA,EAAM,kCAChBA,cAAA,CAAA,aAAA,CAAA,kBAAA,EAAA,EAAmB,OAAc,CACpC,CAAA;AAAA;AAIJ,EAAI,IAAA,CAAC,IAAQ,IAAA,IAAA,EAAM,MAAW,KAAA,CAAA,IAAM,CAAC,IAAO,GAAA,CAAC,CAAK,IAAA,CAAC,OAAU,EAAA;AAC3D,IACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,WAAY,EAAA,EAAA,KAAA,EAAM,cACjB,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,GAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,MAAA;AAAA,QACR,cAAe,EAAA,QAAA;AAAA,QACf,UAAW,EAAA,QAAA;AAAA,QACX,MAAQ,EAAA;AAAA,OAAA;AAAA,mDAEP,eAAgB,EAAA,IAAA;AAAA,KAErB,CAAA;AAAA;AAIJ,EACE,uBAAAA,cAAA,CAAA,aAAA,CAAC,eAAY,KAAM,EAAA,cAAA,EAAe,wBAASA,cAAA,CAAA,aAAA,CAAA,eAAA,EAAA,IAAgB,KACxD,OACC,mBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,GAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,MAAA;AAAA,MACR,cAAe,EAAA,QAAA;AAAA,MACf,UAAW,EAAA,QAAA;AAAA,MACX,MAAQ,EAAA;AAAA,KAAA;AAAA,iDAEP,gBAAiB,EAAA,IAAA;AAAA,GAGpB,mBAAAA,cAAA,CAAA,aAAA,CAAAA,cAAA,CAAA,QAAA,EAAA,IAAA,kBACGA,cAAA,CAAA,aAAA,CAAA,UAAA,EAAA,EAAW,KAAO,EAAA,EAAE,MAAQ,EAAA,WAAA,EAC3B,EAAA,kBAAAA,cAAA,CAAA,aAAA,CAAC,GACE,EAAA,IAAA,EAAA,CAAA,EAAG,IAAK,CAAA,KAAA;AAAA,IACP,UAAA,CAAW,MAAM,aAAa;AAAA,GAC9B,CAAA,cAAA,EAAgB,CAAA,kBAAA,EAChB,aAAa,QAAW,GAAA,MAAA,GAAS,KACnC,CAAA,CACF,CAAK,EAAA,GAAA,EAAI,oCAEX,CAAA,+CACC,GAAI,EAAA,EAAA,EAAA,EAAI,EAAE,MAAA,EAAQ,GAAK,EAAA,EAAA,EAAI,CAAG,EAAA,EAAA,EAAI,GAAG,EAAI,EAAA,CAAA,EAAG,EAAI,EAAA,CAAA,sBAC9CA,cAAA,CAAA,aAAA,CAAA,mBAAA,EAAA,EAAoB,KAAM,EAAA,MAAA,EAAO,QAAO,MACvC,EAAA,kBAAAA,cAAA,CAAA,aAAA;AAAA,IAAC,SAAA;AAAA,IAAA;AAAA,MACC,IAAA;AAAA,MACA,MAAA,EAAQ,EAAE,GAAK,EAAA,EAAA,EAAI,OAAO,EAAI,EAAA,IAAA,EAAM,EAAI,EAAA,MAAA,EAAQ,CAAE;AAAA,KAAA;AAAA,oBAEjDA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,kBACEA,cAAA,CAAA,aAAA,CAAA,gBAAA,EAAA,EAAe,IAAG,WAAY,EAAA,EAAA,EAAG,GAAI,EAAA,EAAA,EAAG,GAAI,EAAA,EAAA,EAAG,GAAI,EAAA,EAAA,EAAG,uBACpDA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAK,MAAO,EAAA,IAAA,EAAK,SAAU,EAAA,SAAA,EAAU,WAAa,EAAA,GAAA,EAAK,mBACvDA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAK,MAAO,EAAA,KAAA,EAAM,SAAU,EAAA,SAAA,EAAU,WAAa,EAAA,GAAA,EAAK,CAC3D,CACA,kBAAAA,cAAA,CAAA,aAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QACC,EAAG,EAAA,iBAAA;AAAA,QACH,EAAG,EAAA,GAAA;AAAA,QACH,EAAG,EAAA,GAAA;AAAA,QACH,EAAG,EAAA,GAAA;AAAA,QACH,EAAG,EAAA;AAAA,OAAA;AAAA,mDAEF,MAAK,EAAA,EAAA,MAAA,EAAO,MAAK,SAAU,EAAA,SAAA,EAAU,aAAa,GAAK,EAAA,CAAA;AAAA,mDACvD,MAAK,EAAA,EAAA,MAAA,EAAO,OAAM,SAAU,EAAA,SAAA,EAAU,aAAa,GAAK,EAAA;AAAA,KAE7D,CAAA;AAAA,oBAEAA,cAAA,CAAA,aAAA;AAAA,MAAC,aAAA;AAAA,MAAA;AAAA,QACC,MAAA,EAAQ,aAAa,MAAS,GAAA,SAAA;AAAA,QAC9B,eAAiB,EAAA,CAAA;AAAA,QACjB,QAAU,EAAA;AAAA;AAAA,KACZ;AAAA,oBAEAA,cAAA,CAAA,aAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,OAAQ,EAAA,MAAA;AAAA,QACR,aAAe,EAAA,CAAA,IAAA,KAAQ,cAAe,CAAA,IAAA,EAAM,QAAQ,CAAA;AAAA,QACpD,KAAA,EAAO,kBAAmB,CAAA,IAAA,EAAM,QAAQ,CAAA;AAAA,QACxC,MAAM,EAAE,IAAA,EAAM,KAAM,CAAA,OAAA,CAAQ,KAAK,OAAQ,EAAA;AAAA,QACzC,QAAU,EAAA,KAAA;AAAA,QACV,QAAU,EAAA,KAAA;AAAA,QACV,OAAS,EAAA,EAAE,IAAM,EAAA,EAAA,EAAI,OAAO,EAAG,EAAA;AAAA,QAC/B,UAAY,EAAA;AAAA;AAAA,KACd;AAAA,oBACAA,cAAA,CAAA,aAAA;AAAA,MAAC,KAAA;AAAA,MAAA;AAAA,QACC,MAAM,EAAE,IAAA,EAAM,KAAM,CAAA,OAAA,CAAQ,KAAK,OAAQ,EAAA;AAAA,QACzC,QAAU,EAAA,KAAA;AAAA,QACV,QAAU,EAAA,KAAA;AAAA,QACV,aAAA,EAAe,CAAS,KAAA,KAAA,KAAA,CAAM,cAAe,EAAA;AAAA,QAC7C,UAAY,EAAA;AAAA;AAAA,KACd;AAAA,oBACAA,cAAA,CAAA,aAAA;AAAA,MAAC,OAAA;AAAA,MAAA;AAAA,QACC,MAAQ,kBAAAA,cAAA,CAAA,aAAA,CAAC,YAAa,EAAA,EAAA,YAAA,EAAc,GAAK,EAAA,CAAA;AAAA,QACzC,OAAA,kBAAUA,cAAA,CAAA,aAAA,CAAA,aAAA,EAAA,EAAc,QAAoB,EAAA;AAAA;AAAA,KAC9C;AAAA,oBACAA,cAAA,CAAA,aAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,IAAK,EAAA,QAAA;AAAA,QACL,OAAQ,EAAA,iBAAA;AAAA,QACR,MAAO,EAAA,MAAA;AAAA,QACP,IAAK,EAAA,uBAAA;AAAA,QACL,WAAa,EAAA;AAAA;AAAA,KACf;AAAA,oBACAA,cAAA,CAAA,aAAA;AAAA,MAAC,IAAA;AAAA,MAAA;AAAA,QACC,IAAK,EAAA,QAAA;AAAA,QACL,OAAQ,EAAA,WAAA;AAAA,QACR,MAAO,EAAA,SAAA;AAAA,QACP,IAAK,EAAA,iBAAA;AAAA,QACL,WAAa,EAAA;AAAA;AAAA,KACf;AAAA,oBACCA,cAAA,CAAA,aAAA,CAAA,MAAA,EAAA,EAAO,OAAS,kBAAAA,cAAA,CAAA,aAAA,CAAC,kBAAa,CAAI,EAAA;AAAA,GAEvC,CACF,CACF,CAEJ,CAAA;AAEJ;;;;"}
|
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,11 +1,11 @@
|
|
1
|
-
import
|
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
4
|
|
5
5
|
const CustomLegend = (props) => {
|
6
6
|
const theme = useTheme();
|
7
7
|
const { payload } = props;
|
8
|
-
return /* @__PURE__ */
|
8
|
+
return /* @__PURE__ */ jsx(
|
9
9
|
"div",
|
10
10
|
{
|
11
11
|
style: {
|
@@ -14,43 +14,48 @@ const CustomLegend = (props) => {
|
|
14
14
|
alignItems: "center",
|
15
15
|
marginLeft: 50,
|
16
16
|
paddingTop: 10
|
17
|
-
}
|
18
|
-
},
|
19
|
-
payload.map((entry) => /* @__PURE__ */ React__default.createElement(
|
20
|
-
"div",
|
21
|
-
{
|
22
|
-
key: entry.value,
|
23
|
-
style: { display: "flex", alignItems: "center", gap: 4 }
|
24
17
|
},
|
25
|
-
|
18
|
+
children: payload.map((entry) => /* @__PURE__ */ jsxs(
|
26
19
|
"div",
|
27
20
|
{
|
28
|
-
style: {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
21
|
+
style: { display: "flex", alignItems: "center", gap: 4 },
|
22
|
+
children: [
|
23
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
24
|
+
/* @__PURE__ */ jsx(
|
25
|
+
"div",
|
26
|
+
{
|
27
|
+
style: {
|
28
|
+
width: 20,
|
29
|
+
height: 3,
|
30
|
+
backgroundColor: entry.color
|
31
|
+
}
|
32
|
+
}
|
33
|
+
),
|
34
|
+
/* @__PURE__ */ jsx(
|
35
|
+
"div",
|
36
|
+
{
|
37
|
+
style: {
|
38
|
+
width: 20,
|
39
|
+
height: 4,
|
40
|
+
backgroundColor: entry.color,
|
41
|
+
opacity: "0.4"
|
42
|
+
}
|
43
|
+
}
|
44
|
+
)
|
45
|
+
] }),
|
46
|
+
/* @__PURE__ */ jsx(
|
47
|
+
Typography,
|
48
|
+
{
|
49
|
+
variant: "body2",
|
50
|
+
style: { color: theme.palette.text.primary, fontSize: "0.875rem" },
|
51
|
+
children: entry.value === "new_users" ? "New users" : "Returning users"
|
52
|
+
}
|
53
|
+
)
|
54
|
+
]
|
50
55
|
},
|
51
|
-
entry.value
|
52
|
-
)
|
53
|
-
|
56
|
+
entry.value
|
57
|
+
))
|
58
|
+
}
|
54
59
|
);
|
55
60
|
};
|
56
61
|
|
@@ -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
|
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: 3,\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' ? 'New users' : 'Returning users'}\n </Typography>\n </div>\n ))}\n </div>\n );\n};\n\nexport default CustomLegend;\n"],"names":[],"mappings":";;;;AAkBM,MAAA,YAAA,GAAe,CAAC,KAAe,KAAA;AACnC,EAAA,MAAM,QAAQ,QAAS,EAAA;AACvB,EAAM,MAAA,EAAE,SAAY,GAAA,KAAA;AAEpB,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,QAAA,EAAA,KAAA,CAAM,KAAU,KAAA,WAAA,GAAc,WAAc,GAAA;AAAA;AAAA;AAC/C;AAAA,SAAA;AAAA,QAzBK,KAAM,CAAA;AAAA,OA2Bd;AAAA;AAAA,GACH;AAEJ;;;;"}
|
@@ -1,4 +1,5 @@
|
|
1
|
-
import
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
2
|
+
import { useState, useRef } from 'react';
|
2
3
|
import { useApi } from '@backstage/core-plugin-api';
|
3
4
|
import Button from '@mui/material/Button';
|
4
5
|
import FileDownloadOutlinedIcon from '@mui/icons-material/FileDownloadOutlined';
|
@@ -9,17 +10,18 @@ import { adoptionInsightsApiRef } from '../../api/index.esm.js';
|
|
9
10
|
import { useDateRange } from '../Header/DateRangeContext.esm.js';
|
10
11
|
|
11
12
|
const ExportCSVButton = () => {
|
12
|
-
const [loading, setLoading] =
|
13
|
+
const [loading, setLoading] = useState(false);
|
13
14
|
const api = useApi(adoptionInsightsApiRef);
|
14
15
|
const { startDateRange, endDateRange } = useDateRange();
|
15
16
|
const theme = useTheme();
|
16
|
-
const debounceRef =
|
17
|
+
const debounceRef = useRef(null);
|
17
18
|
const handleCSVDownload = async () => {
|
18
19
|
try {
|
19
20
|
await api.downloadBlob({
|
20
21
|
type: "active_users",
|
21
22
|
start_date: startDateRange ? format(startDateRange, "yyyy-MM-dd") : void 0,
|
22
23
|
end_date: endDateRange ? format(endDateRange, "yyyy-MM-dd") : void 0,
|
24
|
+
timezone: new Intl.DateTimeFormat().resolvedOptions().timeZone,
|
23
25
|
format: "csv"
|
24
26
|
});
|
25
27
|
} catch (error) {
|
@@ -37,7 +39,7 @@ const ExportCSVButton = () => {
|
|
37
39
|
handleCSVDownload();
|
38
40
|
}, 500);
|
39
41
|
};
|
40
|
-
return /* @__PURE__ */
|
42
|
+
return /* @__PURE__ */ jsx(
|
41
43
|
Box,
|
42
44
|
{
|
43
45
|
sx: {
|
@@ -46,28 +48,28 @@ const ExportCSVButton = () => {
|
|
46
48
|
display: "flex",
|
47
49
|
alignItems: "center",
|
48
50
|
justifyContent: "center"
|
49
|
-
}
|
50
|
-
},
|
51
|
-
/* @__PURE__ */ React__default.createElement(
|
52
|
-
Button,
|
53
|
-
{
|
54
|
-
variant: "text",
|
55
|
-
startIcon: /* @__PURE__ */ React__default.createElement(FileDownloadOutlinedIcon, null),
|
56
|
-
onClick: debouncedHandleCSVDownload,
|
57
|
-
sx: {
|
58
|
-
color: theme.palette.primary.main,
|
59
|
-
textTransform: "none",
|
60
|
-
fontSize: "1rem",
|
61
|
-
fontWeight: 400,
|
62
|
-
textDecoration: "none",
|
63
|
-
"&:hover": {
|
64
|
-
backgroundColor: "transparent",
|
65
|
-
textDecoration: "none"
|
66
|
-
}
|
67
|
-
}
|
68
51
|
},
|
69
|
-
|
70
|
-
|
52
|
+
children: /* @__PURE__ */ jsx(
|
53
|
+
Button,
|
54
|
+
{
|
55
|
+
variant: "text",
|
56
|
+
startIcon: /* @__PURE__ */ jsx(FileDownloadOutlinedIcon, {}),
|
57
|
+
onClick: debouncedHandleCSVDownload,
|
58
|
+
sx: {
|
59
|
+
color: theme.palette.primary.main,
|
60
|
+
textTransform: "none",
|
61
|
+
fontSize: "1rem",
|
62
|
+
fontWeight: 400,
|
63
|
+
textDecoration: "none",
|
64
|
+
"&:hover": {
|
65
|
+
backgroundColor: "transparent",
|
66
|
+
textDecoration: "none"
|
67
|
+
}
|
68
|
+
},
|
69
|
+
children: loading ? "Downloading..." : "Export CSV"
|
70
|
+
}
|
71
|
+
)
|
72
|
+
}
|
71
73
|
);
|
72
74
|
};
|
73
75
|
|
@@ -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
|
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 ? 'Downloading...' : 'Export CSV'}\n </Button>\n </Box>\n );\n};\n\nexport default ExportCSVButton;\n"],"names":[],"mappings":";;;;;;;;;;;AA2BA,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,WAAA,GAAc,OAA8B,IAAI,CAAA;AAEtD,EAAA,MAAM,oBAAoB,YAAY;AACpC,IAAI,IAAA;AACF,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;AAAA,OACT,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;AAAA,OAClB;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,oBAAU,gBAAmB,GAAA;AAAA;AAAA;AAChC;AAAA,GACF;AAEJ;;;;"}
|