@verdaccio/ui-components 2.0.0-6-next.10 → 3.0.0-next-7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (222) hide show
  1. package/CHANGELOG.md +80 -0
  2. package/README.md +1 -1
  3. package/build/Theme/ResetStyles.js +1 -2
  4. package/build/Theme/StyleBaseline.js +1 -2
  5. package/build/Theme/ThemeProvider.js +2 -2
  6. package/build/Theme/colors.js +1 -2
  7. package/build/Theme/index.js +2 -2
  8. package/build/Theme/theme.js +13 -3
  9. package/build/components/ActionBar/ActionBar.js +9 -6
  10. package/build/components/ActionBar/ActionBarAction.js +19 -13
  11. package/build/components/Author/Author.js +16 -9
  12. package/build/components/Author/styles.js +9 -27
  13. package/build/components/CopyClipboard/CopyToClipBoard.js +13 -13
  14. package/build/components/Dependencies/Dependencies.js +1 -2
  15. package/build/components/Dependencies/styles.js +4 -8
  16. package/build/components/Deprecated/Deprecated.js +12 -21
  17. package/build/components/Developers/Developers.js +6 -10
  18. package/build/components/Developers/Title.js +2 -4
  19. package/build/components/Developers/get-unique-developer-values.js +1 -2
  20. package/build/components/Developers/index.js +2 -2
  21. package/build/components/Developers/styles.js +4 -8
  22. package/build/components/Distribution/Dist.js +1 -2
  23. package/build/components/Distribution/styles.js +4 -8
  24. package/build/components/Engines/Engines.js +8 -9
  25. package/build/components/Engines/styles.js +2 -4
  26. package/build/components/ErrorBoundary/ErrorBoundary.js +2 -2
  27. package/build/components/FundButton/FundButton.js +1 -2
  28. package/build/components/HeaderInfoDialog/HeaderInfoDialog.js +1 -2
  29. package/build/components/Heading/Heading.js +3 -4
  30. package/build/components/Help/Help.js +3 -4
  31. package/build/components/Help/styles.js +1 -2
  32. package/build/components/Icons/Earth.js +1 -2
  33. package/build/components/Icons/FileBinary.js +1 -2
  34. package/build/components/Icons/Law.js +1 -2
  35. package/build/components/Icons/License.js +1 -2
  36. package/build/components/Icons/License.js.map +1 -1
  37. package/build/components/Icons/SvgIcon.js +1 -2
  38. package/build/components/Icons/Time.js +1 -2
  39. package/build/components/Icons/Version.js +1 -2
  40. package/build/components/Install/Install.js +12 -10
  41. package/build/components/Install/InstallListItem.js +29 -43
  42. package/build/components/Label/Label.js +1 -2
  43. package/build/components/Link/Link.js +8 -7
  44. package/build/components/Loading/Loading.js +1 -2
  45. package/build/components/Loading/Spinner/Spinner.js +1 -2
  46. package/build/components/Loading/styles.js +2 -4
  47. package/build/components/LoginDialog/LoginDialog.js +3 -4
  48. package/build/components/LoginDialog/LoginDialogCloseButton.js +1 -2
  49. package/build/components/LoginDialog/LoginDialogForm.js +3 -4
  50. package/build/components/LoginDialog/LoginDialogFormError.js +3 -4
  51. package/build/components/LoginDialog/LoginDialogHeader.js +1 -2
  52. package/build/components/Logo/Logo.js +1 -2
  53. package/build/components/MenuItem/MenuItem.js +3 -4
  54. package/build/components/NoItems/NoItems.js +1 -2
  55. package/build/components/NotFound/NotFound.js +3 -4
  56. package/build/components/Package/Package.js +17 -11
  57. package/build/components/Package/Tag/Tag.js +1 -2
  58. package/build/components/Package/Tag/styles.js +1 -2
  59. package/build/components/Package/index.js +2 -2
  60. package/build/components/Package/styles.js +13 -26
  61. package/build/components/PackageList/PackageList.js +1 -2
  62. package/build/components/RawViewer/RawViewer.js +1 -3
  63. package/build/components/Readme/Readme.js +30 -19
  64. package/build/components/Readme/Readme.js.map +1 -1
  65. package/build/components/Readme/github-markdown.css +1198 -0
  66. package/build/components/Readme/utils.js +12 -12
  67. package/build/components/RegistryInfoDialog/RegistryInfoDialog.js +1 -2
  68. package/build/components/RegistryInfoDialog/styles.js +3 -6
  69. package/build/components/Repository/Repository.js +1 -2
  70. package/build/components/Search/AutoComplete/AutoComplete.js +3 -4
  71. package/build/components/Search/AutoComplete/styles.js +2 -4
  72. package/build/components/Search/Search.js +5 -6
  73. package/build/components/Search/SearchItem.js +2 -4
  74. package/build/components/Search/styles.js +2 -4
  75. package/build/components/SettingsMenu/SettingsMenu.js +17 -5
  76. package/build/components/SideBarTittle/SideBarTittle.js +6 -6
  77. package/build/components/SideBarTittle/utils.js +1 -2
  78. package/build/components/TextField/TextField.js +3 -4
  79. package/build/components/UpLinks/UpLinks.js +1 -2
  80. package/build/components/UpLinks/styles.js +3 -6
  81. package/build/components/Versions/HistoryList.js +33 -6
  82. package/build/components/Versions/TagList.js +1 -2
  83. package/build/components/Versions/Versions.js +17 -4
  84. package/build/components/Versions/__partials__/data.json +1 -0
  85. package/build/components/Versions/__partials__/deprecated-versions.json +175 -0
  86. package/build/components/Versions/styles.js +2 -4
  87. package/build/hooks/useLocalStorage.js +1 -2
  88. package/build/hooks/useOnClickOutside.js +1 -2
  89. package/build/index.js +2 -2
  90. package/build/layouts/Version/Version.js +1 -2
  91. package/build/providers/AppConfigurationProvider/AppConfigurationProvider.js +4 -4
  92. package/build/providers/AppConfigurationProvider/index.js +2 -2
  93. package/build/providers/PersistenceSettingProvider/PersistenceSettingProvider.js +5 -5
  94. package/build/providers/PersistenceSettingProvider/index.js +2 -2
  95. package/build/providers/TranslatorProvider/TranslatorProvider.js +3 -4
  96. package/build/providers/TranslatorProvider/TranslatorProvider.spec.js +2 -2
  97. package/build/providers/TranslatorProvider/index.js +2 -2
  98. package/build/providers/VersionProvider/VersionProvider.js +4 -6
  99. package/build/providers/VersionProvider/index.js +2 -2
  100. package/build/sections/Detail/ContainerContent.js +4 -6
  101. package/build/sections/Detail/Detail.js +4 -6
  102. package/build/sections/Detail/ReadmeSection.js +1 -2
  103. package/build/sections/Detail/Tabs.js +1 -2
  104. package/build/sections/Footer/Footer.js +1 -2
  105. package/build/sections/Footer/styles.js +5 -10
  106. package/build/sections/Header/Header.js +3 -4
  107. package/build/sections/Header/HeaderGreetings.js +1 -2
  108. package/build/sections/Header/HeaderLeft.js +1 -2
  109. package/build/sections/Header/HeaderMenu.js +1 -2
  110. package/build/sections/Header/HeaderRight.js +3 -4
  111. package/build/sections/Header/HeaderSettingsDialog.js +1 -2
  112. package/build/sections/Header/HeaderToolTip.js +1 -2
  113. package/build/sections/Header/HeaderToolTipIcon.js +3 -4
  114. package/build/sections/Header/LanguageSwitch.js +7 -10
  115. package/build/sections/Header/RegistryInfoContent/RegistryInfoContent.js +5 -10
  116. package/build/sections/Header/RegistryInfoContent/styles.js +2 -4
  117. package/build/sections/Header/RegistryInfoDialog/RegistryInfoDialog.js +1 -2
  118. package/build/sections/Header/RegistryInfoDialog/styles.js +3 -6
  119. package/build/sections/Header/styles.js +13 -26
  120. package/build/sections/Home/Home.js +3 -4
  121. package/build/sections/SideBar/Sidebar.js +3 -4
  122. package/build/src/__mocks__/react-markdown.d.ts +2 -2
  123. package/build/src/components/Author/styles.d.ts +0 -4
  124. package/build/src/components/CopyClipboard/CopyToClipBoard.d.ts +1 -1
  125. package/build/src/components/Deprecated/Deprecated.d.ts +0 -1
  126. package/build/src/components/Heading/Heading.d.ts +1 -1
  127. package/build/src/components/Icons/DevsIcons/CommonJS.d.ts +2 -2
  128. package/build/src/components/Icons/DevsIcons/ES6Module.d.ts +2 -2
  129. package/build/src/components/Icons/DevsIcons/Git.d.ts +2 -2
  130. package/build/src/components/Icons/DevsIcons/NodeJS.d.ts +2 -2
  131. package/build/src/components/Icons/DevsIcons/TypeScript.d.ts +2 -2
  132. package/build/src/components/Icons/Earth.d.ts +2 -2
  133. package/build/src/components/Icons/FileBinary.d.ts +2 -2
  134. package/build/src/components/Icons/Law.d.ts +2 -2
  135. package/build/src/components/Icons/License.d.ts +2 -2
  136. package/build/src/components/Icons/Managers/Npm.d.ts +2 -2
  137. package/build/src/components/Icons/Managers/Pnpm.d.ts +2 -2
  138. package/build/src/components/Icons/Managers/Yarn.d.ts +2 -2
  139. package/build/src/components/Icons/SvgIcon.d.ts +1 -1
  140. package/build/src/components/Icons/Time.d.ts +2 -2
  141. package/build/src/components/Icons/Version.d.ts +2 -2
  142. package/build/src/components/Install/InstallListItem.d.ts +2 -0
  143. package/build/src/components/Link/Link.d.ts +1 -1
  144. package/build/src/components/LoginDialog/LoginDialog.stories.d.ts +2 -2
  145. package/build/src/components/LoginDialog/LoginDialogForm.d.ts +1 -1
  146. package/build/src/components/LoginDialog/LoginDialogFormError.d.ts +1 -1
  147. package/build/src/components/MenuItem/MenuItem.d.ts +1 -1
  148. package/build/src/components/Readme/Readme.d.ts +1 -1
  149. package/build/src/components/Search/AutoComplete/styles.d.ts +1 -1
  150. package/build/src/components/Search/Search.stories.d.ts +2 -2
  151. package/build/src/components/Search/styles.d.ts +1 -1
  152. package/build/src/components/TextField/TextField.d.ts +1 -1
  153. package/build/src/components/Versions/HistoryList.d.ts +1 -0
  154. package/build/src/sections/Footer/Footer.d.ts +2 -2
  155. package/build/src/sections/Header/HeaderMenu.d.ts +1 -1
  156. package/build/src/sections/Header/LanguageSwitch.d.ts +2 -2
  157. package/build/src/sections/Header/styles.d.ts +1 -1
  158. package/build/src/store/models/login.d.ts +1 -0
  159. package/build/src/types/packageMeta.d.ts +1 -0
  160. package/build/src/utils/__partials__/packageMeta.d.ts +0 -1
  161. package/build/src/utils/index.d.ts +1 -0
  162. package/build/src/utils/loadable.d.ts +2 -2
  163. package/build/src/utils/token.d.ts +1 -0
  164. package/build/store/api.js +1 -2
  165. package/build/store/models/configuration.js +3 -4
  166. package/build/store/models/download.js +1 -3
  167. package/build/store/models/index.js +1 -2
  168. package/build/store/models/login.js +19 -11
  169. package/build/store/models/manifest.js +1 -2
  170. package/build/store/models/packages.js +1 -2
  171. package/build/store/models/search.js +1 -2
  172. package/build/store/storage.js +1 -2
  173. package/build/store/store.js +1 -2
  174. package/build/test/i18n-config.js +1 -2
  175. package/build/utils/__partials__/packageMeta.js +1 -3
  176. package/build/utils/index.js +24 -2
  177. package/build/utils/loadable.js +2 -2
  178. package/build/utils/routes.js +1 -2
  179. package/build/utils/token.js +35 -0
  180. package/build/utils/utils.js +1 -2
  181. package/package.json +28 -25
  182. package/src/Theme/theme.ts +8 -1
  183. package/src/components/ActionBar/ActionBar.stories.tsx +1 -1
  184. package/src/components/ActionBar/ActionBar.test.tsx +17 -10
  185. package/src/components/ActionBar/ActionBar.tsx +16 -12
  186. package/src/components/ActionBar/ActionBarAction.tsx +15 -10
  187. package/src/components/Author/Author.tsx +13 -4
  188. package/src/components/Author/styles.ts +0 -6
  189. package/src/components/CopyClipboard/CopyToClipBoard.tsx +4 -3
  190. package/src/components/Deprecated/Deprecated.tsx +6 -19
  191. package/src/components/Engines/Engines.tsx +5 -5
  192. package/src/components/Help/Help.test.tsx +10 -3
  193. package/src/components/Install/Install.test.tsx +29 -37
  194. package/src/components/Install/Install.tsx +15 -4
  195. package/src/components/Install/InstallListItem.tsx +46 -30
  196. package/src/components/Link/Link.tsx +10 -3
  197. package/src/components/Package/Package.tsx +10 -2
  198. package/src/components/RawViewer/RawViewer.tsx +1 -6
  199. package/src/components/Readme/Readme.tsx +22 -11
  200. package/src/components/Readme/github-markdown.css +1198 -0
  201. package/src/components/Readme/utils.ts +13 -9
  202. package/src/components/Search/Search.test.tsx +2 -2
  203. package/src/components/SettingsMenu/SettingsMenu.tsx +23 -4
  204. package/src/components/SideBarTittle/SideBarTittle.tsx +1 -0
  205. package/src/components/Versions/HistoryList.tsx +29 -1
  206. package/src/components/Versions/Versions.test.tsx +16 -1
  207. package/src/components/Versions/Versions.tsx +17 -1
  208. package/src/components/Versions/__partials__/data.json +1 -0
  209. package/src/components/Versions/__partials__/deprecated-versions.json +175 -0
  210. package/src/providers/AppConfigurationProvider/AppConfigurationProvider.tsx +1 -0
  211. package/src/providers/PersistenceSettingProvider/PersistenceSettingProvider.tsx +2 -0
  212. package/src/sections/Header/HeaderMenu.tsx +1 -1
  213. package/src/sections/Header/LanguageSwitch.tsx +10 -7
  214. package/src/sections/SideBar/Sidebar.test.tsx +7 -3
  215. package/src/store/models/download.ts +0 -1
  216. package/src/store/models/login.test.ts +38 -0
  217. package/src/store/models/login.ts +12 -6
  218. package/src/types/packageMeta.ts +1 -0
  219. package/src/utils/__partials__/packageMeta.ts +0 -1
  220. package/src/utils/index.ts +1 -0
  221. package/src/utils/token.test.ts +54 -0
  222. package/src/utils/token.ts +33 -0
@@ -1,4 +1,6 @@
1
+ /* eslint-disable verdaccio/jsx-spread */
1
2
  import Box from '@mui/material/Box';
3
+ import Stack from '@mui/material/Stack';
2
4
  import React, { useState } from 'react';
3
5
 
4
6
  import { url } from '../../utils';
@@ -40,18 +42,20 @@ const ActionBar: React.FC<Props> = ({ showRaw, showDownloadTarball = true, packa
40
42
 
41
43
  return (
42
44
  <Box alignItems="center" display="flex" marginBottom="14px">
43
- {actions.map((action) => (
44
- <ActionBarAction key={action.type} {...action} />
45
- ))}
46
- {isRawViewerOpen && (
47
- <RawViewer
48
- isOpen={isRawViewerOpen}
49
- onClose={() => {
50
- setIsRawViewerOpen(false);
51
- }}
52
- packageMeta={packageMeta}
53
- />
54
- )}
45
+ <Stack direction="row" spacing={1}>
46
+ {actions.map((action) => (
47
+ <ActionBarAction key={action.type} {...action} />
48
+ ))}
49
+ {isRawViewerOpen && (
50
+ <RawViewer
51
+ isOpen={isRawViewerOpen}
52
+ onClose={() => {
53
+ setIsRawViewerOpen(false);
54
+ }}
55
+ packageMeta={packageMeta}
56
+ />
57
+ )}
58
+ </Stack>
55
59
  </Box>
56
60
  );
57
61
  };
@@ -3,25 +3,21 @@ import BugReportIcon from '@mui/icons-material/BugReport';
3
3
  import DownloadIcon from '@mui/icons-material/CloudDownload';
4
4
  import HomeIcon from '@mui/icons-material/Home';
5
5
  import RawOnIcon from '@mui/icons-material/RawOn';
6
+ import CircularProgress from '@mui/material/CircularProgress';
6
7
  import FabMUI from '@mui/material/Fab';
7
8
  import Tooltip from '@mui/material/Tooltip';
8
9
  import React, { useCallback } from 'react';
9
10
  import { useTranslation } from 'react-i18next';
10
- import { useDispatch } from 'react-redux';
11
+ import { useDispatch, useSelector } from 'react-redux';
11
12
 
12
13
  import { Theme } from '../../Theme';
13
- import { Dispatch } from '../../store/store';
14
+ import { Dispatch, RootState } from '../../store/store';
14
15
  import { Link } from '../Link';
15
16
 
16
17
  export const Fab = styled(FabMUI)<{ theme?: Theme }>(({ theme }) => ({
17
18
  backgroundColor:
18
19
  theme?.palette.mode === 'light' ? theme?.palette.primary.main : theme?.palette.cyanBlue,
19
20
  color: theme?.palette.white,
20
- marginRight: 10,
21
- ':hover': {
22
- color: theme?.palette.mode === 'light' ? theme?.palette.primary.main : theme?.palette.cyanBlue,
23
- background: theme?.palette.white,
24
- },
25
21
  }));
26
22
 
27
23
  type ActionType = 'VISIT_HOMEPAGE' | 'OPEN_AN_ISSUE' | 'DOWNLOAD_TARBALL' | 'RAW_DATA';
@@ -36,6 +32,7 @@ export interface ActionBarActionProps {
36
32
  const ActionBarAction: React.FC<ActionBarActionProps> = ({ type, link, action }) => {
37
33
  const { t } = useTranslation();
38
34
  const dispatch = useDispatch<Dispatch>();
35
+ const isLoading = useSelector((state: RootState) => state?.loading?.models.download);
39
36
 
40
37
  const handleDownload = useCallback(async () => {
41
38
  dispatch.download.getTarball({ link });
@@ -65,9 +62,17 @@ const ActionBarAction: React.FC<ActionBarActionProps> = ({ type, link, action })
65
62
  case 'DOWNLOAD_TARBALL':
66
63
  return (
67
64
  <Tooltip title={t('action-bar-action.download-tarball') as string}>
68
- <Fab data-testid="download-tarball-btn" onClick={handleDownload} size="small">
69
- <DownloadIcon />
70
- </Fab>
65
+ {isLoading ? (
66
+ <CircularProgress sx={{ marginX: 0 }}>
67
+ <Fab data-testid="download-tarball-btn" onClick={handleDownload} size="small">
68
+ <DownloadIcon />
69
+ </Fab>
70
+ </CircularProgress>
71
+ ) : (
72
+ <Fab data-testid="download-tarball-btn" onClick={handleDownload} size="small">
73
+ <DownloadIcon />
74
+ </Fab>
75
+ )}
71
76
  </Tooltip>
72
77
  );
73
78
  case 'RAW_DATA':
@@ -1,11 +1,13 @@
1
+ import { Typography } from '@mui/material';
1
2
  import Avatar from '@mui/material/Avatar';
2
3
  import List from '@mui/material/List';
4
+ import { useTheme } from '@mui/styles';
3
5
  import i18next from 'i18next';
4
6
  import React, { FC } from 'react';
5
7
  import { useTranslation } from 'react-i18next';
6
8
 
7
9
  import { url } from '../../utils';
8
- import { AuthorListItem, AuthorListItemText, StyledText } from './styles';
10
+ import { AuthorListItem, StyledText } from './styles';
9
11
 
10
12
  export function getAuthorName(authorName?: string): string {
11
13
  if (!authorName) {
@@ -26,6 +28,8 @@ export function getAuthorName(authorName?: string): string {
26
28
  const Author: FC<{ packageMeta }> = ({ packageMeta }) => {
27
29
  const { t } = useTranslation();
28
30
 
31
+ const theme = useTheme();
32
+
29
33
  if (!packageMeta) {
30
34
  return null;
31
35
  }
@@ -37,8 +41,13 @@ const Author: FC<{ packageMeta }> = ({ packageMeta }) => {
37
41
  }
38
42
 
39
43
  const { email, name } = author;
40
-
41
- const avatarComponent = <Avatar alt={author.name} src={author.avatar} />;
44
+ const avatarComponent = (
45
+ <Avatar
46
+ alt={author.name}
47
+ src={author.avatar}
48
+ sx={{ width: 40, height: 40, marginRight: theme.spacing(1) }}
49
+ />
50
+ );
42
51
 
43
52
  return (
44
53
  <List subheader={<StyledText variant={'subtitle1'}>{t('sidebar.author.title')}</StyledText>}>
@@ -50,7 +59,7 @@ const Author: FC<{ packageMeta }> = ({ packageMeta }) => {
50
59
  {avatarComponent}
51
60
  </a>
52
61
  )}
53
- {name && <AuthorListItemText primary={getAuthorName(name)} />}
62
+ {name && <Typography variant="subtitle2">{getAuthorName(name)}</Typography>}
54
63
  </AuthorListItem>
55
64
  </List>
56
65
  );
@@ -1,7 +1,6 @@
1
1
  import styled from '@emotion/styled';
2
2
  import { Typography } from '@mui/material';
3
3
  import ListItem from '@mui/material/ListItem';
4
- import ListItemText from '@mui/material/ListItemText';
5
4
 
6
5
  import { Theme } from '../../Theme';
7
6
 
@@ -15,8 +14,3 @@ export const AuthorListItem = styled(ListItem)({
15
14
  backgroundColor: 'transparent',
16
15
  },
17
16
  });
18
-
19
- export const AuthorListItemText = styled(ListItemText)({
20
- padding: '0 10px',
21
- margin: 0,
22
- });
@@ -4,6 +4,7 @@ import IconButton from '@mui/material/IconButton';
4
4
  import Tooltip from '@mui/material/Tooltip';
5
5
  import React from 'react';
6
6
 
7
+ import { Theme } from '../../Theme';
7
8
  import { copyToClipBoardUtility } from './utils';
8
9
 
9
10
  interface Props {
@@ -19,14 +20,14 @@ const Wrapper = styled('div')({
19
20
  justifyContent: 'space-between',
20
21
  });
21
22
 
22
- const Content = styled('span')({
23
+ const Content = styled('span')<{ theme?: Theme }>(({ theme }) => ({
23
24
  display: 'inline-block',
24
25
  overflow: 'hidden',
25
26
  textOverflow: 'ellipsis',
26
27
  height: 'auto',
27
28
  whiteSpace: 'break-spaces',
28
- fontSize: '1rem',
29
- });
29
+ fontSize: theme?.fontSize.sm,
30
+ }));
30
31
 
31
32
  function CopyToClipBoard({ text, children, dataTestId, title, ...props }: Props) {
32
33
  return (
@@ -1,30 +1,17 @@
1
- import Card from '@mui/material/Card';
2
- import CardContent from '@mui/material/CardContent';
3
- import { styled } from '@mui/system';
1
+ import Alert from '@mui/material/Alert';
2
+ import { useTheme } from '@mui/styles';
4
3
  import React from 'react';
5
4
 
6
- import { Theme } from '../../Theme';
7
-
8
- export const CardStyled = styled(Card)<{ theme?: Theme }>(({ theme }) => {
9
- return {
10
- marginTop: theme?.spacing(1),
11
- marginBottom: theme?.spacing(0.5),
12
- backgroundColor: theme?.palette?.error.light,
13
- opacity: '0.9',
14
- color: theme?.palette?.error.contrastText,
15
- fontWeight: 'bold',
16
- };
17
- });
18
-
19
5
  export type Props = {
20
6
  message: string;
21
7
  };
22
8
 
23
9
  const Deprecated: React.FC<Props> = ({ message }) => {
10
+ const theme = useTheme();
24
11
  return (
25
- <CardStyled>
26
- <CardContent>{message}</CardContent>
27
- </CardStyled>
12
+ <Alert severity="warning" sx={{ marginTop: theme.spacing(1), marginBottom: theme.spacing(1) }}>
13
+ {message}
14
+ </Alert>
28
15
  );
29
16
  };
30
17
 
@@ -1,7 +1,7 @@
1
+ import { Typography } from '@mui/material';
1
2
  import Avatar from '@mui/material/Avatar';
2
3
  import Grid from '@mui/material/Grid';
3
4
  import List from '@mui/material/List';
4
- import ListItemText from '@mui/material/ListItemText';
5
5
  import React, { FC } from 'react';
6
6
  import { useTranslation } from 'react-i18next';
7
7
 
@@ -24,7 +24,7 @@ const EngineItem: FC<EngineItemProps> = ({ title, element, engineText }) => (
24
24
  <List subheader={<StyledText variant={'subtitle1'}>{title}</StyledText>}>
25
25
  <EngineListItem>
26
26
  <Avatar sx={{ bgcolor: '#FFF' }}>{element}</Avatar>
27
- <ListItemText primary={engineText} />
27
+ <Typography variant="subtitle2">{engineText}</Typography>
28
28
  </EngineListItem>
29
29
  </List>
30
30
  </Grid>
@@ -68,7 +68,7 @@ const Engine: React.FC<Props> = ({ packageMeta }) => {
68
68
  {engines.npm ? (
69
69
  <EngineItem
70
70
  element={<Npm />}
71
- engineText={engines.node}
71
+ engineText={engines.npm}
72
72
  title={t('sidebar.engines.npm-version')}
73
73
  />
74
74
  ) : null}
@@ -77,7 +77,7 @@ const Engine: React.FC<Props> = ({ packageMeta }) => {
77
77
  <EngineItem
78
78
  element={<Yarn />}
79
79
  engineText={engines.yarn}
80
- title={t('sidebar.engines.npm-version')}
80
+ title={t('sidebar.engines.yarn-version')}
81
81
  />
82
82
  ) : null}
83
83
 
@@ -85,7 +85,7 @@ const Engine: React.FC<Props> = ({ packageMeta }) => {
85
85
  <EngineItem
86
86
  element={<Pnpm />}
87
87
  engineText={engines.pnpm}
88
- title={t('sidebar.engines.npm-version')}
88
+ title={t('sidebar.engines.pnpm-version')}
89
89
  />
90
90
  ) : null}
91
91
  </Grid>
@@ -1,11 +1,18 @@
1
1
  import React from 'react';
2
2
 
3
- import { render } from '../../test/test-react-testing-library';
3
+ import { render, screen } from '../../test/test-react-testing-library';
4
4
  import Help from './Help';
5
5
 
6
6
  describe('<Help /> component', () => {
7
7
  test('should load the component in default state', () => {
8
- const { container } = render(<Help />);
9
- expect(container.firstChild).toMatchSnapshot();
8
+ render(<Help />);
9
+ expect(screen.getByText('help.title')).toBeInTheDocument();
10
+ expect(screen.getByText('help.sub-title')).toBeInTheDocument();
11
+ expect(screen.getByText('help.first-step')).toBeInTheDocument();
12
+ expect(screen.getByText('help.first-step-command-line')).toBeInTheDocument();
13
+ expect(screen.getByText('help.second-step')).toBeInTheDocument();
14
+ expect(screen.getByText('help.second-step-command-line')).toBeInTheDocument();
15
+ expect(screen.getByText('help.third-step')).toBeInTheDocument();
16
+ expect(screen.getByText('button.learn-more')).toBeInTheDocument();
10
17
  });
11
18
  });
@@ -5,6 +5,7 @@ import { PackageManagers } from '@verdaccio/types';
5
5
  import { useConfig } from '../../providers';
6
6
  import { render, screen } from '../../test/test-react-testing-library';
7
7
  import Install from './Install';
8
+ import { getGlobalInstall } from './InstallListItem';
8
9
  import data from './__partials__/data.json';
9
10
 
10
11
  const ComponentToBeRendered: React.FC<{ pkgManagers?: PackageManagers[] }> = () => {
@@ -16,12 +17,9 @@ const ComponentToBeRendered: React.FC<{ pkgManagers?: PackageManagers[] }> = ()
16
17
  describe('<Install />', () => {
17
18
  test('renders correctly', () => {
18
19
  render(<ComponentToBeRendered />);
19
- expect(screen.getByText('sidebar.installation.install-using-pnpm')).toBeInTheDocument();
20
- expect(screen.getByText('sidebar.installation.install-using-yarn')).toBeInTheDocument();
21
- expect(screen.getByText('sidebar.installation.install-using-npm')).toBeInTheDocument();
22
- expect(screen.getByText('sidebar.installation.install-using-npm-command')).toBeInTheDocument();
23
- expect(screen.getByText('sidebar.installation.install-using-yarn-command')).toBeInTheDocument();
24
- expect(screen.getByText('sidebar.installation.install-using-pnpm-command')).toBeInTheDocument();
20
+ expect(screen.getByText('yarn add foo@8.0.0')).toBeInTheDocument();
21
+ expect(screen.getByText('pnpm install foo@8.0.0')).toBeInTheDocument();
22
+ expect(screen.getByText('npm install foo@8.0.0')).toBeInTheDocument();
25
23
  });
26
24
 
27
25
  test('should have 3 children', () => {
@@ -38,47 +36,41 @@ describe('<Install />', () => {
38
36
  render(<ComponentToBeRendered />);
39
37
 
40
38
  expect(screen.getByText('sidebar.installation.title')).toBeTruthy();
41
- expect(screen.queryByText('sidebar.installation.install-using-pnpm')).not.toBeInTheDocument();
42
- expect(screen.queryByText('sidebar.installation.install-using-yarn')).not.toBeInTheDocument();
43
- expect(screen.getByText('sidebar.installation.install-using-npm')).toBeInTheDocument();
44
- expect(screen.getByText('sidebar.installation.install-using-npm-command')).toBeInTheDocument();
45
- expect(
46
- screen.queryByText('sidebar.installation.install-using-yarn-command')
47
- ).not.toBeInTheDocument();
48
- expect(
49
- screen.queryByText('sidebar.installation.install-using-pnpm-command')
50
- ).not.toBeInTheDocument();
39
+ expect(screen.queryByText('pnpm')).not.toBeInTheDocument();
40
+ expect(screen.queryByText('yarn')).not.toBeInTheDocument();
41
+ expect(screen.getByText('npm install foo@8.0.0')).toBeInTheDocument();
51
42
  });
52
43
 
53
44
  test('should have the element YARN', () => {
54
45
  window.__VERDACCIO_BASENAME_UI_OPTIONS.pkgManagers = ['yarn'];
55
46
  render(<ComponentToBeRendered />);
56
47
  expect(screen.getByText('sidebar.installation.title')).toBeTruthy();
57
- expect(screen.queryByText('sidebar.installation.install-using-pnpm')).not.toBeInTheDocument();
58
- expect(screen.getByText('sidebar.installation.install-using-yarn')).toBeInTheDocument();
59
- expect(screen.queryByText('sidebar.installation.install-using-npm')).not.toBeInTheDocument();
60
- expect(
61
- screen.queryByText('sidebar.installation.install-using-npm-command')
62
- ).not.toBeInTheDocument();
63
- expect(screen.getByText('sidebar.installation.install-using-yarn-command')).toBeInTheDocument();
64
- expect(
65
- screen.queryByText('sidebar.installation.install-using-pnpm-command')
66
- ).not.toBeInTheDocument();
48
+ expect(screen.queryByText('pnpm')).not.toBeInTheDocument();
49
+ expect(screen.queryByText('npm')).not.toBeInTheDocument();
50
+ expect(screen.getByText('yarn add foo@8.0.0')).toBeInTheDocument();
67
51
  });
68
52
 
69
53
  test('should have the element PNPM', () => {
70
54
  window.__VERDACCIO_BASENAME_UI_OPTIONS.pkgManagers = ['pnpm'];
71
55
  render(<ComponentToBeRendered />);
72
- expect(screen.getByText('sidebar.installation.title')).toBeTruthy();
73
- expect(screen.getByText('sidebar.installation.install-using-pnpm')).toBeInTheDocument();
74
- expect(screen.queryByText('sidebar.installation.install-using-yarn')).not.toBeInTheDocument();
75
- expect(screen.queryByText('sidebar.installation.install-using-npm')).not.toBeInTheDocument();
76
- expect(
77
- screen.queryByText('sidebar.installation.install-using-npm-command')
78
- ).not.toBeInTheDocument();
79
- expect(
80
- screen.queryByText('sidebar.installation.install-using-yarn-command')
81
- ).not.toBeInTheDocument();
82
- expect(screen.getByText('sidebar.installation.install-using-pnpm-command')).toBeInTheDocument();
56
+ expect(screen.queryByText('pnpm')).not.toBeInTheDocument();
57
+ expect(screen.queryByText('yarn')).not.toBeInTheDocument();
58
+ expect(screen.getByText('pnpm install foo@8.0.0')).toBeInTheDocument();
59
+ });
60
+ });
61
+
62
+ describe('getGlobalInstall', () => {
63
+ test('no global', () => {
64
+ expect(getGlobalInstall(false, 'foo', '1.0.0')).toEqual('1.0.0@foo');
65
+ });
66
+ test('global', () => {
67
+ expect(getGlobalInstall(true, 'foo', '1.0.0')).toEqual('-g 1.0.0@foo');
68
+ });
69
+
70
+ test('yarn no global', () => {
71
+ expect(getGlobalInstall(false, 'foo', '1.0.0', true)).toEqual('1.0.0@foo');
72
+ });
73
+ test('yarn global', () => {
74
+ expect(getGlobalInstall(true, 'foo', '1.0.0', true)).toEqual('1.0.0@foo');
83
75
  });
84
76
  });
@@ -27,7 +27,6 @@ export type Props = {
27
27
  const Install: React.FC<Props> = ({ packageMeta, packageName, configOptions }) => {
28
28
  const { t } = useTranslation();
29
29
  const theme = useTheme();
30
-
31
30
  if (!packageMeta || !packageName) {
32
31
  return null;
33
32
  }
@@ -51,13 +50,25 @@ const Install: React.FC<Props> = ({ packageMeta, packageName, configOptions }) =
51
50
  subheader={<StyledText variant={'subtitle1'}>{t('sidebar.installation.title')}</StyledText>}
52
51
  >
53
52
  {hasNpm && (
54
- <InstallListItem dependencyManager={DependencyManager.NPM} packageName={packageName} />
53
+ <InstallListItem
54
+ dependencyManager={DependencyManager.NPM}
55
+ packageName={packageName}
56
+ packageVersion={packageMeta.latest.version}
57
+ />
55
58
  )}
56
59
  {hasYarn && (
57
- <InstallListItem dependencyManager={DependencyManager.YARN} packageName={packageName} />
60
+ <InstallListItem
61
+ dependencyManager={DependencyManager.YARN}
62
+ packageName={packageName}
63
+ packageVersion={packageMeta.latest.version}
64
+ />
58
65
  )}
59
66
  {hasPnpm && (
60
- <InstallListItem dependencyManager={DependencyManager.PNPM} packageName={packageName} />
67
+ <InstallListItem
68
+ dependencyManager={DependencyManager.PNPM}
69
+ packageName={packageName}
70
+ packageVersion={packageMeta.latest.version}
71
+ />
61
72
  )}
62
73
  </List>
63
74
  </>
@@ -2,8 +2,8 @@ import styled from '@emotion/styled';
2
2
  import Avatar from '@mui/material/Avatar';
3
3
  import ListItem from '@mui/material/ListItem';
4
4
  import ListItemText from '@mui/material/ListItemText';
5
+ import { useTheme } from '@mui/styles';
5
6
  import React from 'react';
6
- import { useTranslation } from 'react-i18next';
7
7
 
8
8
  import { useSettings } from '../../providers/PersistenceSettingProvider';
9
9
  import CopyToClipBoard from '../CopyClipboard';
@@ -35,78 +35,94 @@ export enum DependencyManager {
35
35
  interface Interface {
36
36
  packageName: string;
37
37
  dependencyManager: DependencyManager;
38
+ packageVersion?: string;
38
39
  }
39
40
 
40
- const InstallListItem: React.FC<Interface> = ({ packageName, dependencyManager }) => {
41
- const { t } = useTranslation();
41
+ export function getGlobalInstall(isGlobal, packageVersion, packageName, isYarn = false) {
42
+ const name = isGlobal
43
+ ? `${isYarn ? '' : '-g'} ${packageVersion ? `${packageName}@${packageVersion}` : packageName}`
44
+ : packageVersion
45
+ ? `${packageName}@${packageVersion}`
46
+ : packageName;
47
+
48
+ return name.trim();
49
+ }
50
+
51
+ const InstallListItem: React.FC<Interface> = ({
52
+ packageName,
53
+ dependencyManager,
54
+ packageVersion,
55
+ }) => {
42
56
  const { localSettings } = useSettings();
57
+ const theme = useTheme();
43
58
  const isGlobal = localSettings[packageName]?.global ?? false;
44
- const pkgName = isGlobal ? `-g ${packageName}` : packageName;
45
-
46
59
  switch (dependencyManager) {
47
60
  case DependencyManager.NPM:
48
61
  return (
49
62
  <InstallItem data-testid={'installListItem-npm'}>
50
- <PackageMangerAvatar alt="npm" sx={{ bgcolor: '#FFF' }}>
63
+ <PackageMangerAvatar alt="npm" sx={{ bgcolor: theme.palette.white }}>
51
64
  <Npm />
52
65
  </PackageMangerAvatar>
53
66
  <InstallListItemText
54
67
  primary={
55
68
  <CopyToClipBoard
56
- dataTestId="installYarn"
57
- text={t('sidebar.installation.install-using-npm-command', {
58
- packageName: pkgName,
59
- })}
60
- title={t('sidebar.installation.install-using-npm-command', {
61
- packageName: pkgName,
62
- })}
69
+ dataTestId="instalNpm"
70
+ text={`npm install ${getGlobalInstall(isGlobal, packageVersion, packageName)}`}
71
+ title={`npm install ${getGlobalInstall(isGlobal, packageVersion, packageName)}`}
63
72
  />
64
73
  }
65
- secondary={t('sidebar.installation.install-using-npm')}
66
74
  />
67
75
  </InstallItem>
68
76
  );
69
77
  case DependencyManager.YARN:
70
78
  return (
71
79
  <InstallItem data-testid={'installListItem-yarn'}>
72
- <PackageMangerAvatar alt="yarn" sx={{ bgcolor: '#FFF' }}>
80
+ <PackageMangerAvatar alt="yarn" sx={{ bgcolor: theme.palette.white }}>
73
81
  <Yarn />
74
82
  </PackageMangerAvatar>
75
83
  <InstallListItemText
76
84
  primary={
77
85
  <CopyToClipBoard
78
86
  dataTestId="installYarn"
79
- text={t('sidebar.installation.install-using-yarn-command', {
80
- packageName: pkgName,
81
- })}
82
- title={t('sidebar.installation.install-using-yarn-command', {
83
- packageName: pkgName,
84
- })}
87
+ text={
88
+ isGlobal
89
+ ? `yarn ${localSettings.yarnModern ? '' : 'global'} add ${getGlobalInstall(
90
+ isGlobal,
91
+ packageVersion,
92
+ packageName,
93
+ true
94
+ )}`
95
+ : `yarn add ${getGlobalInstall(isGlobal, packageVersion, packageName, true)}`
96
+ }
97
+ title={
98
+ isGlobal
99
+ ? `yarn global add ${getGlobalInstall(
100
+ isGlobal,
101
+ packageVersion,
102
+ packageName,
103
+ true
104
+ )}`
105
+ : `yarn add ${getGlobalInstall(isGlobal, packageVersion, packageName, true)}`
106
+ }
85
107
  />
86
108
  }
87
- secondary={t('sidebar.installation.install-using-yarn')}
88
109
  />
89
110
  </InstallItem>
90
111
  );
91
112
  case DependencyManager.PNPM:
92
113
  return (
93
114
  <InstallItem data-testid={'installListItem-pnpm'}>
94
- <PackageMangerAvatar alt={'pnpm'} sx={{ bgcolor: '#FFF' }}>
115
+ <PackageMangerAvatar alt={'pnpm'} sx={{ bgcolor: theme.palette.white }}>
95
116
  <Pnpm />
96
117
  </PackageMangerAvatar>
97
118
  <InstallListItemText
98
119
  primary={
99
120
  <CopyToClipBoard
100
121
  dataTestId="installPnpm"
101
- text={t('sidebar.installation.install-using-pnpm-command', {
102
- packageName: pkgName,
103
- })}
104
- title={t('sidebar.installation.install-using-pnpm-command', {
105
- packageName: pkgName,
106
- })}
122
+ text={`pnpm install ${getGlobalInstall(isGlobal, packageVersion, packageName)}`}
123
+ title={`pnpm install ${getGlobalInstall(isGlobal, packageVersion, packageName)}`}
107
124
  />
108
125
  }
109
- secondary={t('sidebar.installation.install-using-pnpm')}
110
126
  />
111
127
  </InstallItem>
112
128
  );
@@ -15,15 +15,22 @@ export const CustomRouterLink = styled(RouterLink)`
15
15
 
16
16
  // TODO: improve any with custom types for a and RouterLink
17
17
  const Link = React.forwardRef<LinkRef, any>(function LinkFunction(
18
- { external, to, children, variant, className },
18
+ { external, to, children, variant, className, onClick },
19
19
  ref
20
20
  ) {
21
21
  return external ? (
22
- <a className={className} href={to} ref={ref} rel="noopener noreferrer" target="_blank">
22
+ <a
23
+ className={className}
24
+ href={to}
25
+ onClick={onClick}
26
+ ref={ref}
27
+ rel="noopener noreferrer"
28
+ target="_blank"
29
+ >
23
30
  <Typography variant={variant ?? 'caption'}>{children}</Typography>
24
31
  </a>
25
32
  ) : (
26
- <CustomRouterLink className={className} innerRef={ref} to={to}>
33
+ <CustomRouterLink className={className} innerRef={ref} onClick={onClick} to={to}>
27
34
  <Typography variant={variant}>{children}</Typography>
28
35
  </CustomRouterLink>
29
36
  );
@@ -4,6 +4,7 @@ import BugReport from '@mui/icons-material/BugReport';
4
4
  import DownloadIcon from '@mui/icons-material/CloudDownload';
5
5
  import HomeIcon from '@mui/icons-material/Home';
6
6
  import { useTheme } from '@mui/material';
7
+ import CircularProgress from '@mui/material/CircularProgress';
7
8
  import Grid from '@mui/material/Grid';
8
9
  import ListItem from '@mui/material/ListItem';
9
10
  import Tooltip from '@mui/material/Tooltip';
@@ -71,6 +72,7 @@ const Package: React.FC<PackageInterface> = ({
71
72
  const dispatch = useDispatch<Dispatch>();
72
73
  const { t } = useTranslation();
73
74
  const theme = useTheme();
75
+ const isLoading = useSelector((state: RootState) => state?.loading?.models.download);
74
76
 
75
77
  const handleDownload = useCallback(
76
78
  async (tarballDist: string) => {
@@ -163,7 +165,6 @@ const Package: React.FC<PackageInterface> = ({
163
165
  dist?.tarball &&
164
166
  url.isURL(dist.tarball) && (
165
167
  <Link
166
- external={true}
167
168
  onClick={() => {
168
169
  handleDownload(dist.tarball);
169
170
  }}
@@ -174,7 +175,13 @@ const Package: React.FC<PackageInterface> = ({
174
175
  title={t('package.tarball')}
175
176
  >
176
177
  <IconButton aria-label={t('package.download')} size="large">
177
- <DownloadIcon />
178
+ {isLoading ? (
179
+ <CircularProgress size={13}>
180
+ <DownloadIcon />
181
+ </CircularProgress>
182
+ ) : (
183
+ <DownloadIcon />
184
+ )}
178
185
  </IconButton>
179
186
  </Tooltip>
180
187
  </Link>
@@ -195,6 +202,7 @@ const Package: React.FC<PackageInterface> = ({
195
202
  container={true}
196
203
  item={true}
197
204
  justify="flex-end"
205
+ spacing={3}
198
206
  xs={true}
199
207
  >
200
208
  {renderHomePageLink()}
@@ -47,12 +47,7 @@ type Props = {
47
47
  const RawViewer: React.FC<Props> = ({ isOpen = false, onClose, packageMeta }) => {
48
48
  const { t } = useTranslation();
49
49
  return (
50
- <Dialog
51
- data-testid={'rawViewer--dialog'}
52
- fullScreen={true}
53
- id="raw-viewer--dialog-container"
54
- open={isOpen}
55
- >
50
+ <Dialog data-testid={'rawViewer--dialog'} fullScreen={true} open={isOpen}>
56
51
  <ViewerTitle id="viewer-title" onClose={onClose}>
57
52
  {t('action-bar-action.raw')}
58
53
  </ViewerTitle>