@red-hat-developer-hub/backstage-plugin-quickstart 1.6.0 → 1.6.2
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 +23 -0
- package/dist/alpha.d.ts +66 -0
- package/dist/alpha.esm.js +3 -0
- package/dist/alpha.esm.js.map +1 -0
- package/dist/components/QuickstartButton/QuickstartButton.esm.js +3 -5
- package/dist/components/QuickstartButton/QuickstartButton.esm.js.map +1 -1
- package/dist/components/QuickstartDrawer.esm.js +5 -7
- package/dist/components/QuickstartDrawer.esm.js.map +1 -1
- package/dist/components/QuickstartDrawerContext.esm.js.map +1 -1
- package/dist/components/QuickstartDrawerProvider.esm.js +25 -5
- package/dist/components/QuickstartDrawerProvider.esm.js.map +1 -1
- package/dist/hooks/useQuickstartRole.esm.js +2 -14
- package/dist/hooks/useQuickstartRole.esm.js.map +1 -1
- package/dist/index.d.ts +59 -64
- package/dist/index.esm.js +4 -1
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +3 -3
- package/dist/plugin.esm.js.map +1 -1
- package/dist/utils/filterQuickstartItems.esm.js.map +1 -1
- package/package.json +28 -14
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,28 @@
|
|
|
1
1
|
# @red-hat-developer-hub/backstage-plugin-quickstart
|
|
2
2
|
|
|
3
|
+
## 1.6.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f1b0f1a: Add package.json exports configuration for alpha module support.
|
|
8
|
+
|
|
9
|
+
- Add exports field to support importing from alpha module
|
|
10
|
+
- Add typesVersions configuration for TypeScript support
|
|
11
|
+
|
|
12
|
+
## 1.6.1
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- def4673: Fixes the issue where the quickstart drawer was reserving space for users with no eligible items
|
|
17
|
+
|
|
18
|
+
- Centralize role determination at provider level to avoid re-fetching on drawer open/close
|
|
19
|
+
- Add multi-layer protection to prevent empty drawer space when user has no eligible quickstart items
|
|
20
|
+
- Remove complex caching logic from useQuickstartRole hook for cleaner implementation
|
|
21
|
+
- Update components to use role from context instead of calling hook directly
|
|
22
|
+
- Fix test mocks to work with new context-based architecture
|
|
23
|
+
|
|
24
|
+
This resolves the issue where the quickstart drawer would open an empty space when the current user has no quickstart items configured for their role.
|
|
25
|
+
|
|
3
26
|
## 1.6.0
|
|
4
27
|
|
|
5
28
|
### Minor Changes
|
package/dist/alpha.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as _backstage_core_plugin_api_alpha from '@backstage/core-plugin-api/alpha';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Translation reference for Quickstart plugin
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
declare const quickstartTranslationRef: _backstage_core_plugin_api_alpha.TranslationRef<"plugin.quickstart", {
|
|
8
|
+
readonly "button.quickstart": string;
|
|
9
|
+
readonly "button.openQuickstartGuide": string;
|
|
10
|
+
readonly "button.closeDrawer": string;
|
|
11
|
+
readonly "button.gotIt": string;
|
|
12
|
+
readonly "footer.progress": string;
|
|
13
|
+
readonly "footer.hide": string;
|
|
14
|
+
readonly "footer.notStarted": string;
|
|
15
|
+
readonly "header.title": string;
|
|
16
|
+
readonly "header.subtitle": string;
|
|
17
|
+
readonly "content.emptyState.title": string;
|
|
18
|
+
readonly "item.expandAriaLabel": string;
|
|
19
|
+
readonly "item.collapseAriaLabel": string;
|
|
20
|
+
readonly "item.expandButtonAriaLabel": string;
|
|
21
|
+
readonly "item.collapseButtonAriaLabel": string;
|
|
22
|
+
readonly "steps.setupAuthentication.title": string;
|
|
23
|
+
readonly "steps.setupAuthentication.description": string;
|
|
24
|
+
readonly "steps.setupAuthentication.ctaTitle": string;
|
|
25
|
+
readonly "steps.configureRbac.title": string;
|
|
26
|
+
readonly "steps.configureRbac.description": string;
|
|
27
|
+
readonly "steps.configureRbac.ctaTitle": string;
|
|
28
|
+
readonly "steps.configureGit.title": string;
|
|
29
|
+
readonly "steps.configureGit.description": string;
|
|
30
|
+
readonly "steps.configureGit.ctaTitle": string;
|
|
31
|
+
readonly "steps.managePlugins.title": string;
|
|
32
|
+
readonly "steps.managePlugins.description": string;
|
|
33
|
+
readonly "steps.managePlugins.ctaTitle": string;
|
|
34
|
+
readonly "steps.importApplication.title": string;
|
|
35
|
+
readonly "steps.importApplication.description": string;
|
|
36
|
+
readonly "steps.importApplication.ctaTitle": string;
|
|
37
|
+
readonly "steps.learnAboutCatalog.title": string;
|
|
38
|
+
readonly "steps.learnAboutCatalog.description": string;
|
|
39
|
+
readonly "steps.learnAboutCatalog.ctaTitle": string;
|
|
40
|
+
readonly "steps.exploreSelfServiceTemplates.title": string;
|
|
41
|
+
readonly "steps.exploreSelfServiceTemplates.description": string;
|
|
42
|
+
readonly "steps.exploreSelfServiceTemplates.ctaTitle": string;
|
|
43
|
+
readonly "steps.findAllLearningPaths.title": string;
|
|
44
|
+
readonly "steps.findAllLearningPaths.description": string;
|
|
45
|
+
readonly "steps.findAllLearningPaths.ctaTitle": string;
|
|
46
|
+
readonly "dev.pageTitle": string;
|
|
47
|
+
readonly "dev.pageDescription": string;
|
|
48
|
+
readonly "dev.drawerControls": string;
|
|
49
|
+
readonly "dev.currentState": string;
|
|
50
|
+
readonly "dev.stateOpen": string;
|
|
51
|
+
readonly "dev.stateClosed": string;
|
|
52
|
+
readonly "dev.instructions": string;
|
|
53
|
+
readonly "dev.step1": string;
|
|
54
|
+
readonly "dev.step2": string;
|
|
55
|
+
readonly "dev.step3": string;
|
|
56
|
+
readonly "dev.step4": string;
|
|
57
|
+
readonly "dev.step5": string;
|
|
58
|
+
}>;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Translation Resource for Quickstart
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
declare const quickstartTranslations: _backstage_core_plugin_api_alpha.TranslationResource<"plugin.quickstart">;
|
|
65
|
+
|
|
66
|
+
export { quickstartTranslationRef, quickstartTranslations };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alpha.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
|
|
@@ -9,7 +9,6 @@ import { useQuickstartDrawerContext } from '../../hooks/useQuickstartDrawerConte
|
|
|
9
9
|
import { useTranslation } from '../../hooks/useTranslation.esm.js';
|
|
10
10
|
import { useApiHolder, configApiRef } from '@backstage/core-plugin-api';
|
|
11
11
|
import { filterQuickstartItemsByRole } from '../../utils/filterQuickstartItems.esm.js';
|
|
12
|
-
import { useQuickstartRole } from '../../hooks/useQuickstartRole.esm.js';
|
|
13
12
|
|
|
14
13
|
const QuickstartButton = ({
|
|
15
14
|
title,
|
|
@@ -18,19 +17,18 @@ const QuickstartButton = ({
|
|
|
18
17
|
}
|
|
19
18
|
}) => {
|
|
20
19
|
const { t } = useTranslation();
|
|
21
|
-
const { toggleDrawer } = useQuickstartDrawerContext();
|
|
20
|
+
const { toggleDrawer, userRole, roleLoading } = useQuickstartDrawerContext();
|
|
22
21
|
const theme = useTheme();
|
|
23
22
|
const apiHolder = useApiHolder();
|
|
24
23
|
const config = apiHolder.get(configApiRef);
|
|
25
24
|
const quickstartItems = config?.has("app.quickstart") ? config.get("app.quickstart") : [];
|
|
26
|
-
const
|
|
27
|
-
const filteredItems = !isLoading && userRole ? filterQuickstartItemsByRole(quickstartItems, userRole) : [];
|
|
25
|
+
const filteredItems = !roleLoading && userRole ? filterQuickstartItemsByRole(quickstartItems, userRole) : [];
|
|
28
26
|
const defaultTitle = t("button.quickstart");
|
|
29
27
|
const handleClick = useCallback(() => {
|
|
30
28
|
toggleDrawer();
|
|
31
29
|
onClick();
|
|
32
30
|
}, [toggleDrawer, onClick]);
|
|
33
|
-
if (!
|
|
31
|
+
if (!roleLoading && filteredItems.length === 0) {
|
|
34
32
|
return null;
|
|
35
33
|
}
|
|
36
34
|
return /* @__PURE__ */ jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickstartButton.esm.js","sources":["../../../src/components/QuickstartButton/QuickstartButton.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 */\n\nimport { CSSProperties, useCallback } from 'react';\nimport MenuItem from '@mui/material/MenuItem';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport { useTheme } from '@mui/material/styles';\nimport WavingHandIcon from '@mui/icons-material/WavingHandOutlined';\nimport { useQuickstartDrawerContext } from '../../hooks/useQuickstartDrawerContext';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { configApiRef, useApiHolder } from '@backstage/core-plugin-api';\nimport { QuickstartItemData } from '../../types';\nimport { filterQuickstartItemsByRole } from '../../utils';\
|
|
1
|
+
{"version":3,"file":"QuickstartButton.esm.js","sources":["../../../src/components/QuickstartButton/QuickstartButton.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 */\n\nimport { CSSProperties, useCallback } from 'react';\nimport MenuItem from '@mui/material/MenuItem';\nimport Box from '@mui/material/Box';\nimport Typography from '@mui/material/Typography';\nimport { useTheme } from '@mui/material/styles';\nimport WavingHandIcon from '@mui/icons-material/WavingHandOutlined';\nimport { useQuickstartDrawerContext } from '../../hooks/useQuickstartDrawerContext';\nimport { useTranslation } from '../../hooks/useTranslation';\nimport { configApiRef, useApiHolder } from '@backstage/core-plugin-api';\nimport { QuickstartItemData } from '../../types';\nimport { filterQuickstartItemsByRole } from '../../utils';\n// Role is now provided through context\n\n/**\n * Props for the QuickstartButton component\n * @public\n */\nexport interface QuickstartButtonProps {\n /**\n * The title text to display in the button\n * @defaultValue 'Quick start'\n */\n title?: string;\n /**\n * Custom CSS styles to apply to the button\n */\n style?: CSSProperties;\n /**\n * Optional callback function to execute when the button is clicked\n */\n onClick?: () => void;\n}\n\n/**\n * Quickstart button component for the global header help dropdown\n * @public\n */\nexport const QuickstartButton = ({\n title,\n style,\n onClick = () => {},\n}: QuickstartButtonProps) => {\n // All hooks must be called at the top level, before any early returns\n const { t } = useTranslation();\n const { toggleDrawer, userRole, roleLoading } = useQuickstartDrawerContext();\n const theme = useTheme();\n\n // Check if there are any quickstart items available for the current user\n const apiHolder = useApiHolder();\n const config = apiHolder.get(configApiRef);\n const quickstartItems: QuickstartItemData[] = config?.has('app.quickstart')\n ? config.get('app.quickstart')\n : [];\n\n const filteredItems =\n !roleLoading && userRole\n ? filterQuickstartItemsByRole(quickstartItems, userRole)\n : [];\n\n const defaultTitle = t('button.quickstart');\n\n const handleClick = useCallback(() => {\n toggleDrawer();\n onClick();\n }, [toggleDrawer, onClick]);\n\n // Hide the button if there are no quickstart items for the user\n if (!roleLoading && filteredItems.length === 0) {\n return null;\n }\n\n return (\n <MenuItem\n sx={{\n width: '100%',\n color: 'inherit',\n ...style,\n }}\n data-testid=\"quickstart-button\"\n onClick={handleClick}\n >\n <Box\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n margin: '8px 0',\n color: 'inherit',\n width: '100%',\n }}\n >\n <Box sx={{ display: 'flex', alignItems: 'center' }}>\n <WavingHandIcon\n sx={{\n fontSize: 20,\n marginRight: '0.5rem',\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n color:\n theme.palette.mode === 'dark'\n ? theme.palette.text.primary\n : theme.palette.text.disabled,\n }}\n />\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'center',\n }}\n >\n <Typography variant=\"body2\" color={theme.palette.text.primary}>\n {title || defaultTitle}\n </Typography>\n </Box>\n </Box>\n </Box>\n </MenuItem>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;AAqDO,MAAM,mBAAmB,CAAC;AAAA,EAC/B,KAAA;AAAA,EACA,KAAA;AAAA,EACA,UAAU,MAAM;AAAA;AAClB,CAA6B,KAAA;AAE3B,EAAM,MAAA,EAAE,CAAE,EAAA,GAAI,cAAe,EAAA;AAC7B,EAAA,MAAM,EAAE,YAAA,EAAc,QAAU,EAAA,WAAA,KAAgB,0BAA2B,EAAA;AAC3E,EAAA,MAAM,QAAQ,QAAS,EAAA;AAGvB,EAAA,MAAM,YAAY,YAAa,EAAA;AAC/B,EAAM,MAAA,MAAA,GAAS,SAAU,CAAA,GAAA,CAAI,YAAY,CAAA;AACzC,EAAM,MAAA,eAAA,GAAwC,QAAQ,GAAI,CAAA,gBAAgB,IACtE,MAAO,CAAA,GAAA,CAAI,gBAAgB,CAAA,GAC3B,EAAC;AAEL,EAAM,MAAA,aAAA,GACJ,CAAC,WAAe,IAAA,QAAA,GACZ,4BAA4B,eAAiB,EAAA,QAAQ,IACrD,EAAC;AAEP,EAAM,MAAA,YAAA,GAAe,EAAE,mBAAmB,CAAA;AAE1C,EAAM,MAAA,WAAA,GAAc,YAAY,MAAM;AACpC,IAAa,YAAA,EAAA;AACb,IAAQ,OAAA,EAAA;AAAA,GACP,EAAA,CAAC,YAAc,EAAA,OAAO,CAAC,CAAA;AAG1B,EAAA,IAAI,CAAC,WAAA,IAAe,aAAc,CAAA,MAAA,KAAW,CAAG,EAAA;AAC9C,IAAO,OAAA,IAAA;AAAA;AAGT,EACE,uBAAA,GAAA;AAAA,IAAC,QAAA;AAAA,IAAA;AAAA,MACC,EAAI,EAAA;AAAA,QACF,KAAO,EAAA,MAAA;AAAA,QACP,KAAO,EAAA,SAAA;AAAA,QACP,GAAG;AAAA,OACL;AAAA,MACA,aAAY,EAAA,mBAAA;AAAA,MACZ,OAAS,EAAA,WAAA;AAAA,MAET,QAAA,kBAAA,GAAA;AAAA,QAAC,GAAA;AAAA,QAAA;AAAA,UACC,EAAI,EAAA;AAAA,YACF,OAAS,EAAA,MAAA;AAAA,YACT,UAAY,EAAA,QAAA;AAAA,YACZ,cAAgB,EAAA,eAAA;AAAA,YAChB,MAAQ,EAAA,OAAA;AAAA,YACR,KAAO,EAAA,SAAA;AAAA,YACP,KAAO,EAAA;AAAA,WACT;AAAA,UAEA,QAAA,kBAAA,IAAA,CAAC,OAAI,EAAI,EAAA,EAAE,SAAS,MAAQ,EAAA,UAAA,EAAY,UACtC,EAAA,QAAA,EAAA;AAAA,4BAAA,GAAA;AAAA,cAAC,cAAA;AAAA,cAAA;AAAA,gBACC,EAAI,EAAA;AAAA,kBACF,QAAU,EAAA,EAAA;AAAA,kBACV,WAAa,EAAA,QAAA;AAAA,kBACb,UAAY,EAAA,CAAA;AAAA,kBACZ,OAAS,EAAA,MAAA;AAAA,kBACT,UAAY,EAAA,QAAA;AAAA,kBACZ,KAAA,EACE,KAAM,CAAA,OAAA,CAAQ,IAAS,KAAA,MAAA,GACnB,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA,OAAA,GACnB,KAAM,CAAA,OAAA,CAAQ,IAAK,CAAA;AAAA;AAC3B;AAAA,aACF;AAAA,4BACA,GAAA;AAAA,cAAC,GAAA;AAAA,cAAA;AAAA,gBACC,EAAI,EAAA;AAAA,kBACF,OAAS,EAAA,MAAA;AAAA,kBACT,aAAe,EAAA,QAAA;AAAA,kBACf,cAAgB,EAAA;AAAA,iBAClB;AAAA,gBAEA,QAAA,kBAAA,GAAA,CAAC,UAAW,EAAA,EAAA,OAAA,EAAQ,OAAQ,EAAA,KAAA,EAAO,MAAM,OAAQ,CAAA,IAAA,CAAK,OACnD,EAAA,QAAA,EAAA,KAAA,IAAS,YACZ,EAAA;AAAA;AAAA;AACF,WACF,EAAA;AAAA;AAAA;AACF;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -4,27 +4,25 @@ import { useApiHolder, configApiRef } from '@backstage/core-plugin-api';
|
|
|
4
4
|
import { Quickstart } from './Quickstart.esm.js';
|
|
5
5
|
import { useQuickstartDrawerContext } from '../hooks/useQuickstartDrawerContext.esm.js';
|
|
6
6
|
import { filterQuickstartItemsByRole } from '../utils/filterQuickstartItems.esm.js';
|
|
7
|
-
import { useQuickstartRole } from '../hooks/useQuickstartRole.esm.js';
|
|
8
7
|
import { useMemo } from 'react';
|
|
9
8
|
|
|
10
9
|
const QuickstartDrawer = () => {
|
|
11
|
-
const { isDrawerOpen, closeDrawer, drawerWidth } = useQuickstartDrawerContext();
|
|
10
|
+
const { isDrawerOpen, closeDrawer, drawerWidth, userRole, roleLoading } = useQuickstartDrawerContext();
|
|
12
11
|
const apiHolder = useApiHolder();
|
|
13
12
|
const config = apiHolder.get(configApiRef);
|
|
14
13
|
const quickstartItems = useMemo(() => {
|
|
15
14
|
return config?.has("app.quickstart") ? config.get("app.quickstart") : [];
|
|
16
15
|
}, [config]);
|
|
17
|
-
const { isLoading, userRole } = useQuickstartRole();
|
|
18
16
|
const eligibleItems = useMemo(() => {
|
|
19
|
-
return !
|
|
20
|
-
}, [
|
|
17
|
+
return !roleLoading && userRole ? filterQuickstartItemsByRole(quickstartItems, userRole) : [];
|
|
18
|
+
}, [roleLoading, userRole, quickstartItems]);
|
|
21
19
|
const filteredItems = useMemo(() => {
|
|
22
20
|
return isDrawerOpen ? eligibleItems : [];
|
|
23
21
|
}, [isDrawerOpen, eligibleItems]);
|
|
24
22
|
if (quickstartItems.length === 0) {
|
|
25
23
|
return null;
|
|
26
24
|
}
|
|
27
|
-
if (!
|
|
25
|
+
if (!roleLoading && eligibleItems.length === 0) {
|
|
28
26
|
return null;
|
|
29
27
|
}
|
|
30
28
|
return /* @__PURE__ */ jsx(
|
|
@@ -53,7 +51,7 @@ const QuickstartDrawer = () => {
|
|
|
53
51
|
{
|
|
54
52
|
quickstartItems: filteredItems,
|
|
55
53
|
handleDrawerClose: closeDrawer,
|
|
56
|
-
isLoading
|
|
54
|
+
isLoading: roleLoading
|
|
57
55
|
}
|
|
58
56
|
)
|
|
59
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickstartDrawer.esm.js","sources":["../../src/components/QuickstartDrawer.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 */\n\nimport Drawer from '@mui/material/Drawer';\nimport { ThemeConfig } from '@red-hat-developer-hub/backstage-plugin-theme';\nimport { configApiRef, useApiHolder } from '@backstage/core-plugin-api';\nimport { Quickstart } from './Quickstart';\nimport { useQuickstartDrawerContext } from '../hooks/useQuickstartDrawerContext';\nimport { QuickstartItemData } from '../types';\nimport { filterQuickstartItemsByRole } from '../utils';\
|
|
1
|
+
{"version":3,"file":"QuickstartDrawer.esm.js","sources":["../../src/components/QuickstartDrawer.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 */\n\nimport Drawer from '@mui/material/Drawer';\nimport { ThemeConfig } from '@red-hat-developer-hub/backstage-plugin-theme';\nimport { configApiRef, useApiHolder } from '@backstage/core-plugin-api';\nimport { Quickstart } from './Quickstart';\nimport { useQuickstartDrawerContext } from '../hooks/useQuickstartDrawerContext';\nimport { QuickstartItemData } from '../types';\nimport { filterQuickstartItemsByRole } from '../utils';\n// Role is now provided through context to avoid re-fetching on drawer open/close\nimport { useMemo } from 'react';\n\nexport const QuickstartDrawer = () => {\n const { isDrawerOpen, closeDrawer, drawerWidth, userRole, roleLoading } =\n useQuickstartDrawerContext();\n\n const apiHolder = useApiHolder();\n const config = apiHolder.get(configApiRef);\n const quickstartItems: QuickstartItemData[] = useMemo(() => {\n return config?.has('app.quickstart')\n ? (config.get('app.quickstart') as QuickstartItemData[])\n : [];\n }, [config]);\n\n // Items available to the user based on role from context\n const eligibleItems = useMemo(() => {\n return !roleLoading && userRole\n ? filterQuickstartItemsByRole(quickstartItems, userRole)\n : [];\n }, [roleLoading, userRole, quickstartItems]);\n\n // Only expose items to the body when drawer is open to avoid re-renders during close\n const filteredItems = useMemo(() => {\n return isDrawerOpen ? eligibleItems : [];\n }, [isDrawerOpen, eligibleItems]);\n\n // No auto-open logic here; the provider initializes per user (visited/open)\n\n // If no quickstart items are configured at all, don't render the drawer to avoid reserving space\n if (quickstartItems.length === 0) {\n return null;\n }\n\n // If there are no items for the user, hide the drawer entirely\n if (!roleLoading && eligibleItems.length === 0) {\n return null;\n }\n\n // No role-fetching or filtering here when the drawer is closed\n\n return (\n <Drawer\n sx={{\n '& .v5-MuiDrawer-paper': {\n width: drawerWidth,\n boxSizing: 'border-box',\n backgroundColor: theme =>\n `${\n (theme as ThemeConfig).palette?.rhdh?.general\n .sidebarBackgroundColor\n }`,\n justifyContent: 'space-between',\n },\n // Only apply header offset when global header exists\n 'body:has(#global-header) &': {\n '& .v5-MuiDrawer-paper': {\n top: '64px !important',\n height: 'calc(100vh - 64px) !important',\n },\n },\n }}\n variant=\"persistent\"\n anchor=\"right\"\n open={isDrawerOpen}\n >\n <Quickstart\n quickstartItems={filteredItems}\n handleDrawerClose={closeDrawer}\n isLoading={roleLoading}\n />\n </Drawer>\n );\n};\n"],"names":[],"mappings":";;;;;;;;AA0BO,MAAM,mBAAmB,MAAM;AACpC,EAAA,MAAM,EAAE,YAAc,EAAA,WAAA,EAAa,aAAa,QAAU,EAAA,WAAA,KACxD,0BAA2B,EAAA;AAE7B,EAAA,MAAM,YAAY,YAAa,EAAA;AAC/B,EAAM,MAAA,MAAA,GAAS,SAAU,CAAA,GAAA,CAAI,YAAY,CAAA;AACzC,EAAM,MAAA,eAAA,GAAwC,QAAQ,MAAM;AAC1D,IAAO,OAAA,MAAA,EAAQ,IAAI,gBAAgB,CAAA,GAC9B,OAAO,GAAI,CAAA,gBAAgB,IAC5B,EAAC;AAAA,GACP,EAAG,CAAC,MAAM,CAAC,CAAA;AAGX,EAAM,MAAA,aAAA,GAAgB,QAAQ,MAAM;AAClC,IAAA,OAAO,CAAC,WAAe,IAAA,QAAA,GACnB,4BAA4B,eAAiB,EAAA,QAAQ,IACrD,EAAC;AAAA,GACJ,EAAA,CAAC,WAAa,EAAA,QAAA,EAAU,eAAe,CAAC,CAAA;AAG3C,EAAM,MAAA,aAAA,GAAgB,QAAQ,MAAM;AAClC,IAAO,OAAA,YAAA,GAAe,gBAAgB,EAAC;AAAA,GACtC,EAAA,CAAC,YAAc,EAAA,aAAa,CAAC,CAAA;AAKhC,EAAI,IAAA,eAAA,CAAgB,WAAW,CAAG,EAAA;AAChC,IAAO,OAAA,IAAA;AAAA;AAIT,EAAA,IAAI,CAAC,WAAA,IAAe,aAAc,CAAA,MAAA,KAAW,CAAG,EAAA;AAC9C,IAAO,OAAA,IAAA;AAAA;AAKT,EACE,uBAAA,GAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,EAAI,EAAA;AAAA,QACF,uBAAyB,EAAA;AAAA,UACvB,KAAO,EAAA,WAAA;AAAA,UACP,SAAW,EAAA,YAAA;AAAA,UACX,iBAAiB,CACf,KAAA,KAAA,CAAA,EACG,MAAsB,OAAS,EAAA,IAAA,EAAM,QACnC,sBACL,CAAA,CAAA;AAAA,UACF,cAAgB,EAAA;AAAA,SAClB;AAAA;AAAA,QAEA,4BAA8B,EAAA;AAAA,UAC5B,uBAAyB,EAAA;AAAA,YACvB,GAAK,EAAA,iBAAA;AAAA,YACL,MAAQ,EAAA;AAAA;AACV;AACF,OACF;AAAA,MACA,OAAQ,EAAA,YAAA;AAAA,MACR,MAAO,EAAA,OAAA;AAAA,MACP,IAAM,EAAA,YAAA;AAAA,MAEN,QAAA,kBAAA,GAAA;AAAA,QAAC,UAAA;AAAA,QAAA;AAAA,UACC,eAAiB,EAAA,aAAA;AAAA,UACjB,iBAAmB,EAAA,WAAA;AAAA,UACnB,SAAW,EAAA;AAAA;AAAA;AACb;AAAA,GACF;AAEJ;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickstartDrawerContext.esm.js","sources":["../../src/components/QuickstartDrawerContext.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 */\n\nimport { createContext } from 'react';\n\n/**\n * Type for QuickstartDrawerContext\n *\n * @public\n */\nexport interface QuickstartDrawerContextType {\n /**\n * The prop to check if the drawer is open\n */\n isDrawerOpen: boolean;\n /**\n * The function to open the drawer\n */\n openDrawer: () => void;\n /**\n * The function to close the drawer\n */\n closeDrawer: () => void;\n /**\n * The function to toggle the drawer state\n */\n toggleDrawer: () => void;\n /**\n * The prop for drawer width\n */\n drawerWidth: number;\n /**\n * The function for setting the drawer width\n */\n setDrawerWidth: React.Dispatch<React.SetStateAction<number>>;\n}\n\n/**\n * @public\n */\nexport const QuickstartDrawerContext = createContext<\n QuickstartDrawerContextType | undefined\n>(undefined);\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"QuickstartDrawerContext.esm.js","sources":["../../src/components/QuickstartDrawerContext.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 */\n\nimport { createContext } from 'react';\nimport { UserRole } from '../types';\n\n/**\n * Type for QuickstartDrawerContext\n *\n * @public\n */\nexport interface QuickstartDrawerContextType {\n /**\n * The prop to check if the drawer is open\n */\n isDrawerOpen: boolean;\n /**\n * The function to open the drawer\n */\n openDrawer: () => void;\n /**\n * The function to close the drawer\n */\n closeDrawer: () => void;\n /**\n * The function to toggle the drawer state\n */\n toggleDrawer: () => void;\n /**\n * The prop for drawer width\n */\n drawerWidth: number;\n /**\n * The function for setting the drawer width\n */\n setDrawerWidth: React.Dispatch<React.SetStateAction<number>>;\n /**\n * The user's role for quickstart functionality\n */\n userRole: UserRole | null;\n /**\n * Whether the role is still loading\n */\n roleLoading: boolean;\n}\n\n/**\n * @public\n */\nexport const QuickstartDrawerContext = createContext<\n QuickstartDrawerContextType | undefined\n>(undefined);\n"],"names":[],"mappings":";;AA8Da,MAAA,uBAAA,GAA0B,cAErC,MAAS;;;;"}
|
|
@@ -6,6 +6,8 @@ import CloseIcon from '@mui/icons-material/Close';
|
|
|
6
6
|
import IconButton from '@mui/material/IconButton';
|
|
7
7
|
import { QuickstartDrawerContext } from './QuickstartDrawerContext.esm.js';
|
|
8
8
|
import { QuickstartDrawer } from './QuickstartDrawer.esm.js';
|
|
9
|
+
import { filterQuickstartItemsByRole } from '../utils/filterQuickstartItems.esm.js';
|
|
10
|
+
import { useQuickstartRole } from '../hooks/useQuickstartRole.esm.js';
|
|
9
11
|
|
|
10
12
|
const QuickstartDrawerProvider = ({ children }) => {
|
|
11
13
|
const [isDrawerOpen, setIsDrawerOpen] = useState(false);
|
|
@@ -15,6 +17,7 @@ const QuickstartDrawerProvider = ({ children }) => {
|
|
|
15
17
|
const [userKey, setUserKey] = useState("guest");
|
|
16
18
|
const identityApi = useApi(identityApiRef);
|
|
17
19
|
const configApi = useApi(configApiRef);
|
|
20
|
+
const { isLoading: roleLoading, userRole } = useQuickstartRole();
|
|
18
21
|
useEffect(() => {
|
|
19
22
|
if (isDrawerOpen) {
|
|
20
23
|
document.body.classList.add("quickstart-drawer-open");
|
|
@@ -65,6 +68,15 @@ const QuickstartDrawerProvider = ({ children }) => {
|
|
|
65
68
|
localStorage.setItem(openKey, "false");
|
|
66
69
|
return;
|
|
67
70
|
}
|
|
71
|
+
const quickstartItems = configApi?.has(
|
|
72
|
+
"app.quickstart"
|
|
73
|
+
) ? configApi.get("app.quickstart") : [];
|
|
74
|
+
const eligibleItems = !roleLoading && userRole ? filterQuickstartItemsByRole(quickstartItems, userRole) : [];
|
|
75
|
+
if (!roleLoading && eligibleItems.length === 0) {
|
|
76
|
+
setIsDrawerOpen(false);
|
|
77
|
+
localStorage.setItem(openKey, "false");
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
68
80
|
const wasOpen = localStorage.getItem(openKey);
|
|
69
81
|
const hasVisited = localStorage.getItem(visitedKey);
|
|
70
82
|
const notificationShown = localStorage.getItem(notificationKey);
|
|
@@ -78,11 +90,17 @@ const QuickstartDrawerProvider = ({ children }) => {
|
|
|
78
90
|
setIsDrawerOpen(false);
|
|
79
91
|
}
|
|
80
92
|
setHasShownNotification(notificationShown === "true");
|
|
81
|
-
}, [userKey, configApi]);
|
|
93
|
+
}, [userKey, configApi, roleLoading, userRole]);
|
|
82
94
|
const openDrawer = () => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
const quickstartItems = configApi?.has(
|
|
96
|
+
"app.quickstart"
|
|
97
|
+
) ? configApi.get("app.quickstart") : [];
|
|
98
|
+
const eligibleItems = !roleLoading && userRole ? filterQuickstartItemsByRole(quickstartItems, userRole) : [];
|
|
99
|
+
if (!roleLoading && eligibleItems.length > 0) {
|
|
100
|
+
setIsDrawerOpen(true);
|
|
101
|
+
const openKey = `quickstart-open:${userKey}`;
|
|
102
|
+
localStorage.setItem(openKey, "true");
|
|
103
|
+
}
|
|
86
104
|
};
|
|
87
105
|
const closeDrawer = () => {
|
|
88
106
|
setIsDrawerOpen(false);
|
|
@@ -111,7 +129,9 @@ const QuickstartDrawerProvider = ({ children }) => {
|
|
|
111
129
|
closeDrawer,
|
|
112
130
|
toggleDrawer,
|
|
113
131
|
setDrawerWidth,
|
|
114
|
-
drawerWidth
|
|
132
|
+
drawerWidth,
|
|
133
|
+
userRole,
|
|
134
|
+
roleLoading
|
|
115
135
|
},
|
|
116
136
|
children: [
|
|
117
137
|
children,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuickstartDrawerProvider.esm.js","sources":["../../src/components/QuickstartDrawerProvider.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 */\n\nimport { useEffect, PropsWithChildren, useState } from 'react';\nimport {\n configApiRef,\n identityApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport Snackbar from '@mui/material/Snackbar';\nimport CloseIcon from '@mui/icons-material/Close';\nimport IconButton from '@mui/material/IconButton';\nimport { QuickstartDrawerContext } from './QuickstartDrawerContext';\nimport { QuickstartDrawer } from './QuickstartDrawer';\n\nexport const QuickstartDrawerProvider = ({ children }: PropsWithChildren) => {\n const [isDrawerOpen, setIsDrawerOpen] = useState<boolean>(false);\n const [showNotification, setShowNotification] = useState(false);\n const [hasShownNotification, setHasShownNotification] = useState(false);\n const [drawerWidth, setDrawerWidth] = useState<number>(500);\n const [userKey, setUserKey] = useState<string>('guest');\n const identityApi = useApi(identityApiRef);\n const configApi = useApi(configApiRef);\n\n // Single useEffect - sets class on document.body\n useEffect(() => {\n if (isDrawerOpen) {\n document.body.classList.add('quickstart-drawer-open');\n document.body.style.setProperty(\n '--quickstart-drawer-width',\n `${drawerWidth}px`,\n );\n } else {\n document.body.classList.remove('quickstart-drawer-open');\n document.body.style.removeProperty('--quickstart-drawer-width');\n }\n\n return () => {\n document.body.classList.remove('quickstart-drawer-open');\n document.body.style.removeProperty('--quickstart-drawer-width');\n };\n }, [isDrawerOpen, drawerWidth]);\n\n // Resolve the current user's identity to scope localStorage keys per user\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const identity = await identityApi.getBackstageIdentity();\n const ref = identity?.userEntityRef?.toLowerCase() || 'guest';\n if (!cancelled) setUserKey(ref);\n } catch (e) {\n if (!cancelled) setUserKey('guest');\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [identityApi]);\n\n // Initialize drawer state based on per-user keys and only when quickstarts exist\n useEffect(() => {\n if (!userKey) return;\n\n // Determine if there are any quickstart items configured globally\n const hasAnyQuickstarts = (() => {\n try {\n if (!configApi?.has('app.quickstart')) return false;\n const items = configApi.get('app.quickstart') as unknown;\n return Array.isArray(items) && items.length > 0;\n } catch {\n return false;\n }\n })();\n\n const openKey = `quickstart-open:${userKey}`;\n const visitedKey = `quickstart-visited:${userKey}`;\n const notificationKey = `quickstart-notification-shown:${userKey}`;\n\n // If no quickstarts are configured, ensure the drawer is closed and don't mark as visited\n if (!hasAnyQuickstarts) {\n setIsDrawerOpen(false);\n // Avoid persisting visited so future addition of items can auto-open\n localStorage.setItem(openKey, 'false');\n return;\n }\n\n const wasOpen = localStorage.getItem(openKey);\n const hasVisited = localStorage.getItem(visitedKey);\n const notificationShown = localStorage.getItem(notificationKey);\n\n if (!hasVisited) {\n setIsDrawerOpen(true);\n localStorage.setItem(visitedKey, 'true');\n localStorage.setItem(openKey, 'true');\n } else if (wasOpen === 'true') {\n setIsDrawerOpen(true);\n } else {\n setIsDrawerOpen(false);\n }\n\n setHasShownNotification(notificationShown === 'true');\n }, [userKey, configApi]);\n\n const openDrawer = () => {\n setIsDrawerOpen(true);\n const openKey = `quickstart-open:${userKey}`;\n localStorage.setItem(openKey, 'true');\n };\n\n const closeDrawer = () => {\n setIsDrawerOpen(false);\n if (!hasShownNotification) {\n setShowNotification(true);\n setHasShownNotification(true);\n const notificationKey = `quickstart-notification-shown:${userKey}`;\n localStorage.setItem(notificationKey, 'true');\n }\n const openKey = `quickstart-open:${userKey}`;\n localStorage.setItem(openKey, 'false');\n };\n\n const toggleDrawer = () => {\n const next = !isDrawerOpen;\n setIsDrawerOpen(next);\n const openKey = `quickstart-open:${userKey}`;\n localStorage.setItem(openKey, next.toString());\n };\n\n const handleNotificationClose = () => setShowNotification(false);\n\n return (\n <QuickstartDrawerContext.Provider\n value={{\n isDrawerOpen,\n openDrawer,\n closeDrawer,\n toggleDrawer,\n setDrawerWidth,\n drawerWidth,\n }}\n >\n {children}\n <QuickstartDrawer />\n <Snackbar\n sx={{ top: '80px !important' }}\n open={showNotification}\n autoHideDuration={10000}\n onClose={handleNotificationClose}\n anchorOrigin={{ vertical: 'top', horizontal: 'right' }}\n message=\"Need help? Visit the Quick Start Guide by clicking on this (?) icon in the header!\"\n action={\n <IconButton\n size=\"small\"\n aria-label=\"close\"\n color=\"inherit\"\n onClick={handleNotificationClose}\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n }\n />\n </QuickstartDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"QuickstartDrawerProvider.esm.js","sources":["../../src/components/QuickstartDrawerProvider.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 */\n\nimport { useEffect, PropsWithChildren, useState } from 'react';\nimport {\n configApiRef,\n identityApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport Snackbar from '@mui/material/Snackbar';\nimport CloseIcon from '@mui/icons-material/Close';\nimport IconButton from '@mui/material/IconButton';\nimport { QuickstartDrawerContext } from './QuickstartDrawerContext';\nimport { QuickstartDrawer } from './QuickstartDrawer';\nimport { QuickstartItemData } from '../types';\nimport { filterQuickstartItemsByRole } from '../utils';\nimport { useQuickstartRole } from '../hooks/useQuickstartRole';\n\n/**\n * Provider component for the Quickstart Drawer functionality\n * @public\n */\nexport const QuickstartDrawerProvider = ({ children }: PropsWithChildren) => {\n const [isDrawerOpen, setIsDrawerOpen] = useState<boolean>(false);\n const [showNotification, setShowNotification] = useState(false);\n const [hasShownNotification, setHasShownNotification] = useState(false);\n const [drawerWidth, setDrawerWidth] = useState<number>(500);\n const [userKey, setUserKey] = useState<string>('guest');\n const identityApi = useApi(identityApiRef);\n const configApi = useApi(configApiRef);\n\n // Determine role once at provider level to avoid re-fetching on drawer open/close\n const { isLoading: roleLoading, userRole } = useQuickstartRole();\n\n // Single useEffect - sets class on document.body\n useEffect(() => {\n if (isDrawerOpen) {\n document.body.classList.add('quickstart-drawer-open');\n document.body.style.setProperty(\n '--quickstart-drawer-width',\n `${drawerWidth}px`,\n );\n } else {\n document.body.classList.remove('quickstart-drawer-open');\n document.body.style.removeProperty('--quickstart-drawer-width');\n }\n\n return () => {\n document.body.classList.remove('quickstart-drawer-open');\n document.body.style.removeProperty('--quickstart-drawer-width');\n };\n }, [isDrawerOpen, drawerWidth]);\n\n // Resolve the current user's identity to scope localStorage keys per user\n useEffect(() => {\n let cancelled = false;\n (async () => {\n try {\n const identity = await identityApi.getBackstageIdentity();\n const ref = identity?.userEntityRef?.toLowerCase() || 'guest';\n if (!cancelled) setUserKey(ref);\n } catch (e) {\n if (!cancelled) setUserKey('guest');\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [identityApi]);\n\n // Initialize drawer state based on per-user keys and only when quickstarts exist\n useEffect(() => {\n if (!userKey) return;\n\n // Determine if there are any quickstart items configured globally\n const hasAnyQuickstarts = (() => {\n try {\n if (!configApi?.has('app.quickstart')) return false;\n const items = configApi.get('app.quickstart') as unknown;\n return Array.isArray(items) && items.length > 0;\n } catch {\n return false;\n }\n })();\n\n const openKey = `quickstart-open:${userKey}`;\n const visitedKey = `quickstart-visited:${userKey}`;\n const notificationKey = `quickstart-notification-shown:${userKey}`;\n\n // If no quickstarts are configured, ensure the drawer is closed and don't mark as visited\n if (!hasAnyQuickstarts) {\n setIsDrawerOpen(false);\n // Avoid persisting visited so future addition of items can auto-open\n localStorage.setItem(openKey, 'false');\n return;\n }\n\n // Check if user has any eligible quickstart items\n const quickstartItems: QuickstartItemData[] = configApi?.has(\n 'app.quickstart',\n )\n ? (configApi.get('app.quickstart') as QuickstartItemData[])\n : [];\n\n const eligibleItems =\n !roleLoading && userRole\n ? filterQuickstartItemsByRole(quickstartItems, userRole)\n : [];\n\n // If user has no eligible items, close the drawer and don't mark as visited\n if (!roleLoading && eligibleItems.length === 0) {\n setIsDrawerOpen(false);\n localStorage.setItem(openKey, 'false');\n return;\n }\n\n // Only proceed with drawer logic if user has eligible items\n const wasOpen = localStorage.getItem(openKey);\n const hasVisited = localStorage.getItem(visitedKey);\n const notificationShown = localStorage.getItem(notificationKey);\n\n if (!hasVisited) {\n setIsDrawerOpen(true);\n localStorage.setItem(visitedKey, 'true');\n localStorage.setItem(openKey, 'true');\n } else if (wasOpen === 'true') {\n setIsDrawerOpen(true);\n } else {\n setIsDrawerOpen(false);\n }\n\n setHasShownNotification(notificationShown === 'true');\n }, [userKey, configApi, roleLoading, userRole]);\n\n const openDrawer = () => {\n // Check if user has eligible items before opening\n const quickstartItems: QuickstartItemData[] = configApi?.has(\n 'app.quickstart',\n )\n ? (configApi.get('app.quickstart') as QuickstartItemData[])\n : [];\n\n const eligibleItems =\n !roleLoading && userRole\n ? filterQuickstartItemsByRole(quickstartItems, userRole)\n : [];\n\n // Only open if user has eligible items\n if (!roleLoading && eligibleItems.length > 0) {\n setIsDrawerOpen(true);\n const openKey = `quickstart-open:${userKey}`;\n localStorage.setItem(openKey, 'true');\n }\n };\n\n const closeDrawer = () => {\n setIsDrawerOpen(false);\n if (!hasShownNotification) {\n setShowNotification(true);\n setHasShownNotification(true);\n const notificationKey = `quickstart-notification-shown:${userKey}`;\n localStorage.setItem(notificationKey, 'true');\n }\n const openKey = `quickstart-open:${userKey}`;\n localStorage.setItem(openKey, 'false');\n };\n\n const toggleDrawer = () => {\n const next = !isDrawerOpen;\n setIsDrawerOpen(next);\n const openKey = `quickstart-open:${userKey}`;\n localStorage.setItem(openKey, next.toString());\n };\n\n const handleNotificationClose = () => setShowNotification(false);\n\n return (\n <QuickstartDrawerContext.Provider\n value={{\n isDrawerOpen,\n openDrawer,\n closeDrawer,\n toggleDrawer,\n setDrawerWidth,\n drawerWidth,\n userRole,\n roleLoading,\n }}\n >\n {children}\n <QuickstartDrawer />\n <Snackbar\n sx={{ top: '80px !important' }}\n open={showNotification}\n autoHideDuration={10000}\n onClose={handleNotificationClose}\n anchorOrigin={{ vertical: 'top', horizontal: 'right' }}\n message=\"Need help? Visit the Quick Start Guide by clicking on this (?) icon in the header!\"\n action={\n <IconButton\n size=\"small\"\n aria-label=\"close\"\n color=\"inherit\"\n onClick={handleNotificationClose}\n >\n <CloseIcon fontSize=\"small\" />\n </IconButton>\n }\n />\n </QuickstartDrawerContext.Provider>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -15,9 +15,9 @@ const useQuickstartRole = () => {
|
|
|
15
15
|
const credentials = await identityApi.getCredentials();
|
|
16
16
|
const identity = await identityApi.getBackstageIdentity();
|
|
17
17
|
const hasValidToken = credentials?.token && credentials.token.length > 10;
|
|
18
|
-
const
|
|
18
|
+
const userEntityRef = identity?.userEntityRef || "";
|
|
19
19
|
const ownershipRefs = identity?.ownershipEntityRefs || [];
|
|
20
|
-
const isGuest =
|
|
20
|
+
const isGuest = userEntityRef.toLowerCase().includes("guest") || userEntityRef === "user:default/guest" || !hasValidToken && ownershipRefs.length === 0;
|
|
21
21
|
const isAuthenticated = !isGuest;
|
|
22
22
|
return { isAuthenticated, identity, credentials };
|
|
23
23
|
} catch (error) {
|
|
@@ -25,29 +25,17 @@ const useQuickstartRole = () => {
|
|
|
25
25
|
}
|
|
26
26
|
}, [identityApi]);
|
|
27
27
|
if (authLoading) return { isLoading: true, userRole: null };
|
|
28
|
-
const userEntityRef = authResult?.identity?.userEntityRef || "guest";
|
|
29
|
-
const cacheKey = `quickstart-role:${userEntityRef}:rbac:${isRBACEnabled ? "1" : "0"}`;
|
|
30
|
-
const cachedRole = typeof window !== "undefined" ? sessionStorage.getItem(cacheKey) : null;
|
|
31
|
-
if (cachedRole === "admin" || cachedRole === "developer") {
|
|
32
|
-
return { isLoading: false, userRole: cachedRole };
|
|
33
|
-
}
|
|
34
28
|
if (loading) return { isLoading: true, userRole: null };
|
|
35
29
|
const isUserAuthorized = authResult?.isAuthenticated ?? false;
|
|
36
30
|
if (!isUserAuthorized) {
|
|
37
31
|
return { isLoading: false, userRole: "admin" };
|
|
38
32
|
}
|
|
39
33
|
if (!isRBACEnabled) {
|
|
40
|
-
if (typeof window !== "undefined")
|
|
41
|
-
sessionStorage.setItem(cacheKey, "admin");
|
|
42
34
|
return { isLoading: false, userRole: "admin" };
|
|
43
35
|
}
|
|
44
36
|
if (allowed) {
|
|
45
|
-
if (typeof window !== "undefined")
|
|
46
|
-
sessionStorage.setItem(cacheKey, "admin");
|
|
47
37
|
return { isLoading: false, userRole: "admin" };
|
|
48
38
|
}
|
|
49
|
-
if (typeof window !== "undefined")
|
|
50
|
-
sessionStorage.setItem(cacheKey, "developer");
|
|
51
39
|
return { isLoading: false, userRole: "developer" };
|
|
52
40
|
};
|
|
53
41
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useQuickstartRole.esm.js","sources":["../../src/hooks/useQuickstartRole.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 */\n\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n configApiRef,\n identityApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { policyEntityCreatePermission } from '@backstage-community/plugin-rbac-common';\nimport { useAsync } from 'react-use';\nimport { UserRole } from '../types';\n\n/**\n * Determines the user's role for quickstart functionality based on RBAC permissions and user authorization.\n *\n * Business Logic:\n * - Guest user(unauthorized): show admin items\n * - Authorized user + NO RBAC enabled: show admin items\n * - Authorized user + RBAC enabled:\n * - if user has admin permission => show configured admin items\n * - if user doesn't have admin permission => show configured developer items\n *\n * @returns Object with isLoading boolean and userRole ('admin' | 'developer' | null)\n */\nexport const useQuickstartRole = (): {\n isLoading: boolean;\n userRole: UserRole | null;\n} => {\n const config = useApi(configApiRef);\n const identityApi = useApi(identityApiRef);\n const isRBACEnabled =\n config.getOptionalBoolean('permission.enabled') ?? false;\n const { loading, allowed } = usePermission({\n permission: policyEntityCreatePermission,\n });\n\n // Check user authorization status by examining identity and credentials\n const { value: authResult, loading: authLoading } = useAsync(async () => {\n try {\n const credentials = await identityApi.getCredentials();\n const identity = await identityApi.getBackstageIdentity();\n\n // Check multiple indicators to determine if user is authenticated (not a guest)\n const hasValidToken = credentials?.token && credentials.token.length > 10; // Real tokens are longer\n const userEntityRef = identity?.userEntityRef || '';\n const ownershipRefs = identity?.ownershipEntityRefs || [];\n\n const isGuest =\n userEntityRef.toLowerCase().includes('guest') ||\n userEntityRef === 'user:default/guest' ||\n (!hasValidToken && ownershipRefs.length === 0);\n\n const isAuthenticated = !isGuest;\n\n return { isAuthenticated, identity, credentials };\n } catch (error) {\n return { isAuthenticated: false, identity: null, credentials: null };\n }\n }, [identityApi]);\n\n // When auth is still resolving, return loading\n if (authLoading) return { isLoading: true, userRole: null };\n\n //
|
|
1
|
+
{"version":3,"file":"useQuickstartRole.esm.js","sources":["../../src/hooks/useQuickstartRole.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 */\n\nimport { usePermission } from '@backstage/plugin-permission-react';\nimport {\n configApiRef,\n identityApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { policyEntityCreatePermission } from '@backstage-community/plugin-rbac-common';\nimport { useAsync } from 'react-use';\nimport { UserRole } from '../types';\n\n/**\n * Determines the user's role for quickstart functionality based on RBAC permissions and user authorization.\n *\n * Business Logic:\n * - Guest user(unauthorized): show admin items\n * - Authorized user + NO RBAC enabled: show admin items\n * - Authorized user + RBAC enabled:\n * - if user has admin permission => show configured admin items\n * - if user doesn't have admin permission => show configured developer items\n *\n * @returns Object with isLoading boolean and userRole ('admin' | 'developer' | null)\n */\nexport const useQuickstartRole = (): {\n isLoading: boolean;\n userRole: UserRole | null;\n} => {\n const config = useApi(configApiRef);\n const identityApi = useApi(identityApiRef);\n const isRBACEnabled =\n config.getOptionalBoolean('permission.enabled') ?? false;\n const { loading, allowed } = usePermission({\n permission: policyEntityCreatePermission,\n });\n\n // Check user authorization status by examining identity and credentials\n const { value: authResult, loading: authLoading } = useAsync(async () => {\n try {\n const credentials = await identityApi.getCredentials();\n const identity = await identityApi.getBackstageIdentity();\n\n // Check multiple indicators to determine if user is authenticated (not a guest)\n const hasValidToken = credentials?.token && credentials.token.length > 10; // Real tokens are longer\n const userEntityRef = identity?.userEntityRef || '';\n const ownershipRefs = identity?.ownershipEntityRefs || [];\n\n const isGuest =\n userEntityRef.toLowerCase().includes('guest') ||\n userEntityRef === 'user:default/guest' ||\n (!hasValidToken && ownershipRefs.length === 0);\n\n const isAuthenticated = !isGuest;\n\n return { isAuthenticated, identity, credentials };\n } catch (error) {\n return { isAuthenticated: false, identity: null, credentials: null };\n }\n }, [identityApi]);\n\n // When auth is still resolving, return loading\n if (authLoading) return { isLoading: true, userRole: null };\n\n // If permission is still loading, report loading\n if (loading) return { isLoading: true, userRole: null };\n\n // Check if user is authorized (authenticated, not a guest)\n const isUserAuthorized = authResult?.isAuthenticated ?? false;\n\n // Unauthorized user: show admin items\n if (!isUserAuthorized) {\n return { isLoading: false, userRole: 'admin' };\n }\n\n // Authorized user + NO RBAC enabled: show admin items\n if (!isRBACEnabled) {\n return { isLoading: false, userRole: 'admin' };\n }\n\n // Authorized user + RBAC enabled: check permissions\n // If user has admin permission => show configured admin items\n if (allowed) {\n return { isLoading: false, userRole: 'admin' };\n }\n\n // If user doesn't have admin permission => show configured developer items\n return { isLoading: false, userRole: 'developer' };\n};\n"],"names":[],"mappings":";;;;;AAsCO,MAAM,oBAAoB,MAG5B;AACH,EAAM,MAAA,MAAA,GAAS,OAAO,YAAY,CAAA;AAClC,EAAM,MAAA,WAAA,GAAc,OAAO,cAAc,CAAA;AACzC,EAAA,MAAM,aACJ,GAAA,MAAA,CAAO,kBAAmB,CAAA,oBAAoB,CAAK,IAAA,KAAA;AACrD,EAAA,MAAM,EAAE,OAAA,EAAS,OAAQ,EAAA,GAAI,aAAc,CAAA;AAAA,IACzC,UAAY,EAAA;AAAA,GACb,CAAA;AAGD,EAAA,MAAM,EAAE,KAAO,EAAA,UAAA,EAAY,SAAS,WAAY,EAAA,GAAI,SAAS,YAAY;AACvE,IAAI,IAAA;AACF,MAAM,MAAA,WAAA,GAAc,MAAM,WAAA,CAAY,cAAe,EAAA;AACrD,MAAM,MAAA,QAAA,GAAW,MAAM,WAAA,CAAY,oBAAqB,EAAA;AAGxD,MAAA,MAAM,aAAgB,GAAA,WAAA,EAAa,KAAS,IAAA,WAAA,CAAY,MAAM,MAAS,GAAA,EAAA;AACvE,MAAM,MAAA,aAAA,GAAgB,UAAU,aAAiB,IAAA,EAAA;AACjD,MAAM,MAAA,aAAA,GAAgB,QAAU,EAAA,mBAAA,IAAuB,EAAC;AAExD,MAAA,MAAM,OACJ,GAAA,aAAA,CAAc,WAAY,EAAA,CAAE,QAAS,CAAA,OAAO,CAC5C,IAAA,aAAA,KAAkB,oBACjB,IAAA,CAAC,aAAiB,IAAA,aAAA,CAAc,MAAW,KAAA,CAAA;AAE9C,MAAA,MAAM,kBAAkB,CAAC,OAAA;AAEzB,MAAO,OAAA,EAAE,eAAiB,EAAA,QAAA,EAAU,WAAY,EAAA;AAAA,aACzC,KAAO,EAAA;AACd,MAAA,OAAO,EAAE,eAAiB,EAAA,KAAA,EAAO,QAAU,EAAA,IAAA,EAAM,aAAa,IAAK,EAAA;AAAA;AACrE,GACF,EAAG,CAAC,WAAW,CAAC,CAAA;AAGhB,EAAA,IAAI,aAAoB,OAAA,EAAE,SAAW,EAAA,IAAA,EAAM,UAAU,IAAK,EAAA;AAG1D,EAAA,IAAI,SAAgB,OAAA,EAAE,SAAW,EAAA,IAAA,EAAM,UAAU,IAAK,EAAA;AAGtD,EAAM,MAAA,gBAAA,GAAmB,YAAY,eAAmB,IAAA,KAAA;AAGxD,EAAA,IAAI,CAAC,gBAAkB,EAAA;AACrB,IAAA,OAAO,EAAE,SAAA,EAAW,KAAO,EAAA,QAAA,EAAU,OAAQ,EAAA;AAAA;AAI/C,EAAA,IAAI,CAAC,aAAe,EAAA;AAClB,IAAA,OAAO,EAAE,SAAA,EAAW,KAAO,EAAA,QAAA,EAAU,OAAQ,EAAA;AAAA;AAK/C,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,OAAO,EAAE,SAAA,EAAW,KAAO,EAAA,QAAA,EAAU,OAAQ,EAAA;AAAA;AAI/C,EAAA,OAAO,EAAE,SAAA,EAAW,KAAO,EAAA,QAAA,EAAU,WAAY,EAAA;AACnD;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
3
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
4
|
import { CSSProperties, PropsWithChildren } from 'react';
|
|
4
|
-
|
|
5
|
+
export { quickstartTranslationRef, quickstartTranslations } from './alpha.js';
|
|
6
|
+
import '@backstage/core-plugin-api/alpha';
|
|
5
7
|
|
|
6
8
|
/**
|
|
7
9
|
* Props for the QuickstartButton component
|
|
@@ -22,6 +24,11 @@ interface QuickstartButtonProps {
|
|
|
22
24
|
*/
|
|
23
25
|
onClick?: () => void;
|
|
24
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* Quickstart button component for the global header help dropdown
|
|
29
|
+
* @public
|
|
30
|
+
*/
|
|
31
|
+
declare const QuickstartButton: ({ title, style, onClick, }: QuickstartButtonProps) => react_jsx_runtime.JSX.Element | null;
|
|
25
32
|
|
|
26
33
|
/**
|
|
27
34
|
* Quick start plugin
|
|
@@ -29,18 +36,44 @@ interface QuickstartButtonProps {
|
|
|
29
36
|
* @public
|
|
30
37
|
*/
|
|
31
38
|
declare const quickstartPlugin: _backstage_core_plugin_api.BackstagePlugin<{}, {}, {}>;
|
|
39
|
+
|
|
32
40
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
41
|
+
* Call-to-action data for quickstart items
|
|
35
42
|
* @public
|
|
36
43
|
*/
|
|
37
|
-
|
|
44
|
+
interface QuickstartItemCtaData {
|
|
45
|
+
/** The text to display for the CTA button */
|
|
46
|
+
text: string;
|
|
47
|
+
/** Translation key for the CTA text */
|
|
48
|
+
textKey?: string;
|
|
49
|
+
/** The URL to navigate to when clicked */
|
|
50
|
+
link: string;
|
|
51
|
+
}
|
|
38
52
|
/**
|
|
39
|
-
*
|
|
40
|
-
*
|
|
53
|
+
* Configuration data for a quickstart item
|
|
41
54
|
* @public
|
|
42
55
|
*/
|
|
43
|
-
|
|
56
|
+
interface QuickstartItemData {
|
|
57
|
+
/** The title of the quickstart item */
|
|
58
|
+
title: string;
|
|
59
|
+
/** Translation key for the title */
|
|
60
|
+
titleKey?: string;
|
|
61
|
+
/** Array of roles that can access this item (defaults to ['admin'] if not specified) */
|
|
62
|
+
roles?: string[];
|
|
63
|
+
/** Icon identifier for the item */
|
|
64
|
+
icon?: string;
|
|
65
|
+
/** Description text for the item */
|
|
66
|
+
description: string;
|
|
67
|
+
/** Translation key for the description */
|
|
68
|
+
descriptionKey?: string;
|
|
69
|
+
/** Call-to-action configuration */
|
|
70
|
+
cta?: QuickstartItemCtaData;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* User role type for quickstart functionality
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
type UserRole = 'admin' | 'developer';
|
|
44
77
|
|
|
45
78
|
/**
|
|
46
79
|
* Type for QuickstartDrawerContext
|
|
@@ -72,6 +105,14 @@ interface QuickstartDrawerContextType {
|
|
|
72
105
|
* The function for setting the drawer width
|
|
73
106
|
*/
|
|
74
107
|
setDrawerWidth: React.Dispatch<React.SetStateAction<number>>;
|
|
108
|
+
/**
|
|
109
|
+
* The user's role for quickstart functionality
|
|
110
|
+
*/
|
|
111
|
+
userRole: UserRole | null;
|
|
112
|
+
/**
|
|
113
|
+
* Whether the role is still loading
|
|
114
|
+
*/
|
|
115
|
+
roleLoading: boolean;
|
|
75
116
|
}
|
|
76
117
|
|
|
77
118
|
/**
|
|
@@ -82,67 +123,21 @@ interface QuickstartDrawerContextType {
|
|
|
82
123
|
declare const useQuickstartDrawerContext: () => QuickstartDrawerContextType;
|
|
83
124
|
|
|
84
125
|
/**
|
|
85
|
-
*
|
|
126
|
+
* Provider component for the Quickstart Drawer functionality
|
|
86
127
|
* @public
|
|
87
128
|
*/
|
|
88
|
-
declare const
|
|
89
|
-
readonly "button.quickstart": string;
|
|
90
|
-
readonly "button.openQuickstartGuide": string;
|
|
91
|
-
readonly "button.closeDrawer": string;
|
|
92
|
-
readonly "button.gotIt": string;
|
|
93
|
-
readonly "footer.progress": string;
|
|
94
|
-
readonly "footer.hide": string;
|
|
95
|
-
readonly "footer.notStarted": string;
|
|
96
|
-
readonly "header.title": string;
|
|
97
|
-
readonly "header.subtitle": string;
|
|
98
|
-
readonly "content.emptyState.title": string;
|
|
99
|
-
readonly "item.expandAriaLabel": string;
|
|
100
|
-
readonly "item.collapseAriaLabel": string;
|
|
101
|
-
readonly "item.expandButtonAriaLabel": string;
|
|
102
|
-
readonly "item.collapseButtonAriaLabel": string;
|
|
103
|
-
readonly "steps.setupAuthentication.title": string;
|
|
104
|
-
readonly "steps.setupAuthentication.description": string;
|
|
105
|
-
readonly "steps.setupAuthentication.ctaTitle": string;
|
|
106
|
-
readonly "steps.configureRbac.title": string;
|
|
107
|
-
readonly "steps.configureRbac.description": string;
|
|
108
|
-
readonly "steps.configureRbac.ctaTitle": string;
|
|
109
|
-
readonly "steps.configureGit.title": string;
|
|
110
|
-
readonly "steps.configureGit.description": string;
|
|
111
|
-
readonly "steps.configureGit.ctaTitle": string;
|
|
112
|
-
readonly "steps.managePlugins.title": string;
|
|
113
|
-
readonly "steps.managePlugins.description": string;
|
|
114
|
-
readonly "steps.managePlugins.ctaTitle": string;
|
|
115
|
-
readonly "steps.importApplication.title": string;
|
|
116
|
-
readonly "steps.importApplication.description": string;
|
|
117
|
-
readonly "steps.importApplication.ctaTitle": string;
|
|
118
|
-
readonly "steps.learnAboutCatalog.title": string;
|
|
119
|
-
readonly "steps.learnAboutCatalog.description": string;
|
|
120
|
-
readonly "steps.learnAboutCatalog.ctaTitle": string;
|
|
121
|
-
readonly "steps.exploreSelfServiceTemplates.title": string;
|
|
122
|
-
readonly "steps.exploreSelfServiceTemplates.description": string;
|
|
123
|
-
readonly "steps.exploreSelfServiceTemplates.ctaTitle": string;
|
|
124
|
-
readonly "steps.findAllLearningPaths.title": string;
|
|
125
|
-
readonly "steps.findAllLearningPaths.description": string;
|
|
126
|
-
readonly "steps.findAllLearningPaths.ctaTitle": string;
|
|
127
|
-
readonly "dev.pageTitle": string;
|
|
128
|
-
readonly "dev.pageDescription": string;
|
|
129
|
-
readonly "dev.drawerControls": string;
|
|
130
|
-
readonly "dev.currentState": string;
|
|
131
|
-
readonly "dev.stateOpen": string;
|
|
132
|
-
readonly "dev.stateClosed": string;
|
|
133
|
-
readonly "dev.instructions": string;
|
|
134
|
-
readonly "dev.step1": string;
|
|
135
|
-
readonly "dev.step2": string;
|
|
136
|
-
readonly "dev.step3": string;
|
|
137
|
-
readonly "dev.step4": string;
|
|
138
|
-
readonly "dev.step5": string;
|
|
139
|
-
}>;
|
|
129
|
+
declare const QuickstartDrawerProvider: ({ children }: PropsWithChildren) => react_jsx_runtime.JSX.Element;
|
|
140
130
|
|
|
141
131
|
/**
|
|
142
|
-
*
|
|
132
|
+
* Filters quickstart items based on user role.
|
|
133
|
+
*
|
|
134
|
+
* @param items - Array of quickstart items to filter
|
|
135
|
+
* @param userRole - The user's role ('admin' or 'developer')
|
|
136
|
+
* @returns Filtered array of quickstart items available to the user
|
|
137
|
+
*
|
|
143
138
|
* @public
|
|
144
139
|
*/
|
|
145
|
-
declare const
|
|
140
|
+
declare const filterQuickstartItemsByRole: (items: QuickstartItemData[], userRole: string) => QuickstartItemData[];
|
|
146
141
|
|
|
147
|
-
export { QuickstartButton, QuickstartDrawerProvider,
|
|
148
|
-
export type { QuickstartButtonProps, QuickstartDrawerContextType };
|
|
142
|
+
export { QuickstartButton, QuickstartDrawerProvider, filterQuickstartItemsByRole, quickstartPlugin, useQuickstartDrawerContext };
|
|
143
|
+
export type { QuickstartButtonProps, QuickstartDrawerContextType, QuickstartItemCtaData, QuickstartItemData, UserRole };
|
package/dist/index.esm.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { unstable_ClassNameGenerator } from '@mui/material/className';
|
|
2
|
-
export {
|
|
2
|
+
export { quickstartPlugin } from './plugin.esm.js';
|
|
3
3
|
export { useQuickstartDrawerContext } from './hooks/useQuickstartDrawerContext.esm.js';
|
|
4
|
+
export { QuickstartButton } from './components/QuickstartButton/QuickstartButton.esm.js';
|
|
5
|
+
export { QuickstartDrawerProvider } from './components/QuickstartDrawerProvider.esm.js';
|
|
4
6
|
export { quickstartTranslations } from './translations/index.esm.js';
|
|
7
|
+
export { filterQuickstartItemsByRole } from './utils/filterQuickstartItems.esm.js';
|
|
5
8
|
export { quickstartTranslationRef } from './translations/ref.esm.js';
|
|
6
9
|
|
|
7
10
|
unstable_ClassNameGenerator.configure((componentName) => {
|
package/dist/index.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.esm.js","sources":["../src/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 */\n\nimport { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className';\n\nClassNameGenerator.configure(componentName => {\n return componentName.startsWith('v5-')\n ? componentName\n : `v5-${componentName}`;\n});\n\nexport * from './plugin';\n\nexport { useQuickstartDrawerContext } from './hooks/useQuickstartDrawerContext';\nexport type { QuickstartDrawerContextType } from './components/QuickstartDrawerContext';\n\nexport {\n quickstartTranslations,\n quickstartTranslationRef,\n} from './translations';\n"],"names":["ClassNameGenerator"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../src/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 */\n\nimport { unstable_ClassNameGenerator as ClassNameGenerator } from '@mui/material/className';\n\nClassNameGenerator.configure(componentName => {\n return componentName.startsWith('v5-')\n ? componentName\n : `v5-${componentName}`;\n});\n\nexport * from './plugin';\n\nexport { useQuickstartDrawerContext } from './hooks/useQuickstartDrawerContext';\nexport type { QuickstartDrawerContextType } from './components/QuickstartDrawerContext';\n/**\n * @public\n */\nexport type {\n UserRole,\n QuickstartItemData,\n QuickstartItemCtaData,\n} from './types';\nexport { QuickstartButton } from './components/QuickstartButton/QuickstartButton';\nexport type { QuickstartButtonProps } from './components/QuickstartButton/QuickstartButton';\n/**\n * @public\n */\nexport { QuickstartDrawerProvider } from './components/QuickstartDrawerProvider';\n\nexport {\n quickstartTranslations,\n quickstartTranslationRef,\n} from './translations';\n\nexport { filterQuickstartItemsByRole } from './utils';\n"],"names":["ClassNameGenerator"],"mappings":";;;;;;;;;AAkBAA,2BAAA,CAAmB,UAAU,CAAiB,aAAA,KAAA;AAC5C,EAAA,OAAO,cAAc,UAAW,CAAA,KAAK,CACjC,GAAA,aAAA,GACA,MAAM,aAAa,CAAA,CAAA;AACzB,CAAC,CAAA"}
|
package/dist/plugin.esm.js
CHANGED
|
@@ -9,7 +9,7 @@ const quickstartPlugin = createPlugin({
|
|
|
9
9
|
resources: [quickstartTranslationRef]
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
-
|
|
12
|
+
quickstartPlugin.provide(
|
|
13
13
|
createComponentExtension({
|
|
14
14
|
name: "QuickstartDrawerProvider",
|
|
15
15
|
component: {
|
|
@@ -19,7 +19,7 @@ const QuickstartDrawerProvider = quickstartPlugin.provide(
|
|
|
19
19
|
}
|
|
20
20
|
})
|
|
21
21
|
);
|
|
22
|
-
|
|
22
|
+
quickstartPlugin.provide(
|
|
23
23
|
createComponentExtension({
|
|
24
24
|
name: "QuickstartButton",
|
|
25
25
|
component: {
|
|
@@ -30,5 +30,5 @@ const QuickstartButton = quickstartPlugin.provide(
|
|
|
30
30
|
})
|
|
31
31
|
);
|
|
32
32
|
|
|
33
|
-
export {
|
|
33
|
+
export { quickstartPlugin };
|
|
34
34
|
//# sourceMappingURL=plugin.esm.js.map
|
package/dist/plugin.esm.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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 */\n\nimport {\n createComponentExtension,\n createPlugin,\n} from '@backstage/core-plugin-api';\nimport { PropsWithChildren } from 'react';\nimport { QuickstartButtonProps } from './components/QuickstartButton/QuickstartButton';\nimport { quickstartTranslationRef } from './translations';\n\nexport type { QuickstartButtonProps } from './components/QuickstartButton/QuickstartButton';\n\n/**\n * Quick start plugin\n *\n * @public\n */\nexport const quickstartPlugin = createPlugin({\n id: 'quickstart',\n __experimentalTranslations: {\n availableLanguages: ['en', 'de', 'fr', 'es'],\n resources: [quickstartTranslationRef],\n },\n} as any);\n\n/**\n * Quick start drawer provider\n *\n * @public\n */\nexport const QuickstartDrawerProvider: React.ComponentType<PropsWithChildren> =\n quickstartPlugin.provide(\n createComponentExtension({\n name: 'QuickstartDrawerProvider',\n component: {\n lazy: () =>\n import('./components/QuickstartDrawerProvider').then(\n m => m.QuickstartDrawerProvider,\n ),\n },\n }),\n );\n\n/**\n * Quick start button for global header help dropdown\n *\n * @public\n */\nexport const QuickstartButton: React.ComponentType<QuickstartButtonProps> =\n quickstartPlugin.provide(\n createComponentExtension({\n name: 'QuickstartButton',\n component: {\n lazy: () =>\n import('./components/QuickstartButton/QuickstartButton').then(\n m => m.QuickstartButton,\n ),\n },\n }),\n );\n"],"names":[],"mappings":";;;;AA+BO,MAAM,mBAAmB,YAAa,CAAA;AAAA,EAC3C,EAAI,EAAA,YAAA;AAAA,EACJ,0BAA4B,EAAA;AAAA,IAC1B,kBAAoB,EAAA,CAAC,IAAM,EAAA,IAAA,EAAM,MAAM,IAAI,CAAA;AAAA,IAC3C,SAAA,EAAW,CAAC,wBAAwB;AAAA;AAExC,CAAQ;
|
|
1
|
+
{"version":3,"file":"plugin.esm.js","sources":["../src/plugin.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 */\n\nimport {\n createComponentExtension,\n createPlugin,\n} from '@backstage/core-plugin-api';\nimport { PropsWithChildren } from 'react';\nimport { QuickstartButtonProps } from './components/QuickstartButton/QuickstartButton';\nimport { quickstartTranslationRef } from './translations';\n\nexport type { QuickstartButtonProps } from './components/QuickstartButton/QuickstartButton';\n\n/**\n * Quick start plugin\n *\n * @public\n */\nexport const quickstartPlugin = createPlugin({\n id: 'quickstart',\n __experimentalTranslations: {\n availableLanguages: ['en', 'de', 'fr', 'es'],\n resources: [quickstartTranslationRef],\n },\n} as any);\n\n/**\n * Quick start drawer provider\n *\n * @public\n */\nexport const QuickstartDrawerProvider: React.ComponentType<PropsWithChildren> =\n quickstartPlugin.provide(\n createComponentExtension({\n name: 'QuickstartDrawerProvider',\n component: {\n lazy: () =>\n import('./components/QuickstartDrawerProvider').then(\n m => m.QuickstartDrawerProvider,\n ),\n },\n }),\n );\n\n/**\n * Quick start button for global header help dropdown\n *\n * @public\n */\nexport const QuickstartButton: React.ComponentType<QuickstartButtonProps> =\n quickstartPlugin.provide(\n createComponentExtension({\n name: 'QuickstartButton',\n component: {\n lazy: () =>\n import('./components/QuickstartButton/QuickstartButton').then(\n m => m.QuickstartButton,\n ),\n },\n }),\n );\n"],"names":[],"mappings":";;;;AA+BO,MAAM,mBAAmB,YAAa,CAAA;AAAA,EAC3C,EAAI,EAAA,YAAA;AAAA,EACJ,0BAA4B,EAAA;AAAA,IAC1B,kBAAoB,EAAA,CAAC,IAAM,EAAA,IAAA,EAAM,MAAM,IAAI,CAAA;AAAA,IAC3C,SAAA,EAAW,CAAC,wBAAwB;AAAA;AAExC,CAAQ;AAQN,gBAAiB,CAAA,OAAA;AAAA,EACf,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,0BAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAM,EAAA,MACJ,OAAO,8CAAuC,CAAE,CAAA,IAAA;AAAA,QAC9C,OAAK,CAAE,CAAA;AAAA;AACT;AACJ,GACD;AACH;AAQA,gBAAiB,CAAA,OAAA;AAAA,EACf,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,kBAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAM,EAAA,MACJ,OAAO,uDAAgD,CAAE,CAAA,IAAA;AAAA,QACvD,OAAK,CAAE,CAAA;AAAA;AACT;AACJ,GACD;AACH;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filterQuickstartItems.esm.js","sources":["../../src/utils/filterQuickstartItems.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 */\n\nimport { QuickstartItemData } from '../types';\n\nexport const filterQuickstartItemsByRole = (\n items: QuickstartItemData[],\n userRole: string,\n): QuickstartItemData[] => {\n return items.filter(item => {\n // If roles is undefined or empty, default to 'admin'\n const roles = item.roles?.length ? item.roles : ['admin'];\n return roles.includes(userRole);\n });\n};\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"filterQuickstartItems.esm.js","sources":["../../src/utils/filterQuickstartItems.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 */\n\nimport { QuickstartItemData } from '../types';\n\n/**\n * Filters quickstart items based on user role.\n *\n * @param items - Array of quickstart items to filter\n * @param userRole - The user's role ('admin' or 'developer')\n * @returns Filtered array of quickstart items available to the user\n *\n * @public\n */\nexport const filterQuickstartItemsByRole = (\n items: QuickstartItemData[],\n userRole: string,\n): QuickstartItemData[] => {\n return items.filter(item => {\n // If roles is undefined or empty, default to 'admin'\n const roles = item.roles?.length ? item.roles : ['admin'];\n return roles.includes(userRole);\n });\n};\n"],"names":[],"mappings":"AA2Ba,MAAA,2BAAA,GAA8B,CACzC,KAAA,EACA,QACyB,KAAA;AACzB,EAAO,OAAA,KAAA,CAAM,OAAO,CAAQ,IAAA,KAAA;AAE1B,IAAA,MAAM,QAAQ,IAAK,CAAA,KAAA,EAAO,SAAS,IAAK,CAAA,KAAA,GAAQ,CAAC,OAAO,CAAA;AACxD,IAAO,OAAA,KAAA,CAAM,SAAS,QAAQ,CAAA;AAAA,GAC/B,CAAA;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@red-hat-developer-hub/backstage-plugin-quickstart",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
|
-
"main": "dist/index.esm.js",
|
|
6
|
-
"types": "dist/index.d.ts",
|
|
5
|
+
"main": "./dist/index.esm.js",
|
|
6
|
+
"types": "./dist/index.d.ts",
|
|
7
7
|
"publishConfig": {
|
|
8
|
-
"access": "public"
|
|
9
|
-
"main": "dist/index.esm.js",
|
|
10
|
-
"types": "dist/index.d.ts"
|
|
8
|
+
"access": "public"
|
|
11
9
|
},
|
|
12
10
|
"repository": {
|
|
13
11
|
"type": "git",
|
|
@@ -39,6 +37,7 @@
|
|
|
39
37
|
"@backstage/theme": "^0.6.8",
|
|
40
38
|
"@mui/icons-material": "5.18.0",
|
|
41
39
|
"@mui/material": "5.18.0",
|
|
40
|
+
"@red-hat-developer-hub/backstage-plugin-theme": "^0.10.0",
|
|
42
41
|
"react-use": "^17.6.0"
|
|
43
42
|
},
|
|
44
43
|
"peerDependencies": {
|
|
@@ -50,26 +49,41 @@
|
|
|
50
49
|
"@backstage/dev-utils": "^1.1.13",
|
|
51
50
|
"@backstage/plugin-permission-common": "^0.9.1",
|
|
52
51
|
"@backstage/test-utils": "^1.7.11",
|
|
53
|
-
"@red-hat-developer-hub/backstage-plugin-theme": "^0.10.0",
|
|
54
52
|
"@testing-library/jest-dom": "^6.0.0",
|
|
55
53
|
"@testing-library/react": "^14.0.0",
|
|
56
54
|
"@testing-library/user-event": "^14.0.0",
|
|
57
55
|
"msw": "^1.0.0",
|
|
58
56
|
"react": "^16.13.1 || ^17.0.0 || ^18.0.0"
|
|
59
57
|
},
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
58
|
+
"exports": {
|
|
59
|
+
".": {
|
|
60
|
+
"import": "./dist/index.esm.js",
|
|
61
|
+
"types": "./dist/index.d.ts",
|
|
62
|
+
"default": "./dist/index.esm.js"
|
|
63
|
+
},
|
|
64
|
+
"./alpha": {
|
|
65
|
+
"import": "./dist/alpha.esm.js",
|
|
66
|
+
"types": "./dist/alpha.d.ts",
|
|
67
|
+
"default": "./dist/alpha.esm.js"
|
|
68
|
+
},
|
|
69
|
+
"./package.json": "./package.json"
|
|
70
|
+
},
|
|
67
71
|
"typesVersions": {
|
|
68
72
|
"*": {
|
|
73
|
+
"alpha": [
|
|
74
|
+
"dist/alpha.d.ts"
|
|
75
|
+
],
|
|
69
76
|
"package.json": [
|
|
70
77
|
"package.json"
|
|
71
78
|
]
|
|
72
79
|
}
|
|
73
80
|
},
|
|
81
|
+
"files": [
|
|
82
|
+
"dist",
|
|
83
|
+
"dist-scalprum",
|
|
84
|
+
"config.d.ts",
|
|
85
|
+
"app-config.dynamic.yaml"
|
|
86
|
+
],
|
|
87
|
+
"configSchema": "config.d.ts",
|
|
74
88
|
"module": "./dist/index.esm.js"
|
|
75
89
|
}
|