@verdaccio/ui-components 3.0.0-next-7.7 → 3.0.0-next-7.8

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 (300) hide show
  1. package/.eslintrc +1 -1
  2. package/CHANGELOG.md +6 -0
  3. package/build/Theme/theme.js +3 -3
  4. package/build/components/ActionBar/ActionBar.js +3 -1
  5. package/build/components/ActionBar/ActionBarAction.js +7 -6
  6. package/build/components/Author/Author.js +13 -42
  7. package/build/components/CopyClipboard/utils.js +3 -12
  8. package/build/components/Dependencies/Dependencies.js +12 -13
  9. package/build/components/Dependencies/DependencyBlock.js +5 -4
  10. package/build/components/Developers/DeveloperType.js +12 -0
  11. package/build/components/Developers/Developers.js +20 -22
  12. package/build/components/Developers/Title.js +5 -9
  13. package/build/components/Developers/index.js +4 -4
  14. package/build/components/Distribution/Dist.js +1 -1
  15. package/build/components/Distribution/styles.js +10 -23
  16. package/build/components/Engines/Engines.js +7 -1
  17. package/build/components/Engines/styles.js +6 -6
  18. package/build/components/FundButton/FundButton.js +7 -8
  19. package/build/components/HeaderInfoDialog/HeaderInfoDialog.js +2 -1
  20. package/build/components/Icons/DevsIcons/CommonJS.js +1 -12
  21. package/build/components/Icons/DevsIcons/ES6Module.js +2 -13
  22. package/build/components/Icons/DevsIcons/Git.js +1 -12
  23. package/build/components/Icons/DevsIcons/NodeJS.js +1 -12
  24. package/build/components/Icons/DevsIcons/TypeScript.js +1 -12
  25. package/build/components/Icons/FileBinary.js +11 -5
  26. package/build/components/Icons/Law.js +12 -6
  27. package/build/components/Icons/Managers/Npm.js +1 -12
  28. package/build/components/Icons/Managers/Pnpm.js +1 -12
  29. package/build/components/Icons/Managers/Yarn.js +1 -12
  30. package/build/components/Install/Install.js +23 -18
  31. package/build/components/Install/InstallListItem.js +19 -18
  32. package/build/components/Keywords/KeywordListItems.js +34 -0
  33. package/build/components/Keywords/Keywords.js +39 -0
  34. package/build/{sections/Header/RegistryInfoDialog → components/Keywords}/index.js +2 -2
  35. package/build/components/Link/Link.js +4 -16
  36. package/build/components/Link/index.js +1 -1
  37. package/build/components/LinkExternal/LinkExternal.js +32 -0
  38. package/build/components/LinkExternal/index.js +14 -0
  39. package/build/components/Loading/styles.js +3 -2
  40. package/build/components/LoginDialog/LoginDialog.js +12 -1
  41. package/build/components/LoginDialog/LoginDialogCloseButton.js +3 -2
  42. package/build/components/LoginDialog/LoginDialogForm.js +2 -14
  43. package/build/components/LoginDialog/LoginDialogFormError.js +3 -2
  44. package/build/components/Logo/Logo.js +13 -6
  45. package/build/components/Package/Package.js +43 -34
  46. package/build/components/Package/styles.js +46 -58
  47. package/build/components/Person/Person.js +48 -0
  48. package/build/components/Person/PersonTooltip.js +22 -0
  49. package/build/components/{Package/Tag → Person}/index.js +2 -2
  50. package/build/components/Person/utils.js +17 -0
  51. package/build/components/RawViewer/RawViewer.js +11 -5
  52. package/build/components/Readme/Readme.js +15 -6
  53. package/build/components/Readme/Readme.js.map +1 -1
  54. package/build/components/Readme/Readme.spec.js +19 -0
  55. package/build/components/Readme/Readme.spec.js.map +1 -1
  56. package/build/components/Readme/utils.js +2 -5
  57. package/build/components/RegistryInfoDialog/styles.js +9 -10
  58. package/build/components/Repository/Repository.js +19 -31
  59. package/build/components/Search/AutoComplete/styles.js +4 -41
  60. package/build/components/Search/Search.js +4 -2
  61. package/build/components/Search/SearchItem.js +51 -38
  62. package/build/components/Search/utils.js +23 -0
  63. package/build/components/SettingsMenu/SettingsMenu.js +35 -9
  64. package/build/components/SideBarTitle/SideBarTitle.js +16 -6
  65. package/build/components/UpLinks/UpLinks.js +35 -6
  66. package/build/components/UpLinks/UplinkLink.js +22 -0
  67. package/build/components/UpLinks/styles.js +5 -4
  68. package/build/components/Versions/HistoryList.js +8 -5
  69. package/build/components/Versions/TagList.js +8 -4
  70. package/build/components/Versions/Versions.js +30 -7
  71. package/build/index.js +27 -3
  72. package/build/providers/AppConfigurationProvider/AppConfigurationProvider.js +1 -0
  73. package/build/providers/PersistenceSettingProvider/PersistenceSettingProvider.js +1 -0
  74. package/build/sections/Detail/Detail.js +6 -2
  75. package/build/sections/Detail/Tabs.js +4 -3
  76. package/build/sections/Footer/Footer.js +17 -8
  77. package/build/sections/Footer/styles.js +13 -10
  78. package/build/sections/Header/HeaderLeft.js +14 -17
  79. package/build/sections/Header/HeaderMenu.js +1 -1
  80. package/build/sections/Header/HeaderRight.js +12 -3
  81. package/build/sections/Header/HeaderSettingsDialog.js +2 -2
  82. package/build/sections/Header/styles.js +43 -82
  83. package/build/sections/SideBar/Sidebar.js +10 -15
  84. package/build/src/Theme/ThemeProvider.test.d.ts +1 -0
  85. package/build/src/components/Author/Author.d.ts +0 -5
  86. package/build/src/components/CopyClipboard/CopyToClipBoard.test.d.ts +1 -0
  87. package/build/src/components/Dependencies/Dependencies.d.ts +0 -1
  88. package/build/src/components/Developers/DeveloperType.d.ts +4 -0
  89. package/build/src/components/Developers/Developers.d.ts +1 -4
  90. package/build/src/components/Developers/Title.d.ts +1 -4
  91. package/build/src/components/Developers/index.d.ts +2 -1
  92. package/build/src/components/Distribution/styles.d.ts +0 -1
  93. package/build/src/components/ErrorBoundary/ErrorBoundary.test.d.ts +1 -0
  94. package/build/src/components/HeaderInfoDialog/HeaderInfoDialog.test.d.ts +1 -0
  95. package/build/src/components/Heading/Heading.test.d.ts +1 -0
  96. package/build/src/components/Icons/Icons.test.d.ts +1 -0
  97. package/build/src/components/Install/InstallListItem.d.ts +1 -1
  98. package/build/src/components/Keywords/KeywordListItems.d.ts +5 -0
  99. package/build/src/components/Keywords/Keywords.d.ts +6 -0
  100. package/build/src/components/Keywords/Keywords.stories.d.ts +5 -0
  101. package/build/src/components/Keywords/Keywords.test.d.ts +1 -0
  102. package/build/src/components/Keywords/index.d.ts +1 -0
  103. package/build/src/components/Link/Link.d.ts +0 -3
  104. package/build/src/components/Link/Link.test.d.ts +1 -0
  105. package/build/src/components/Link/index.d.ts +1 -1
  106. package/build/src/components/LinkExternal/LinkExternal.d.ts +3 -0
  107. package/build/src/components/LinkExternal/LinkExternal.test.d.ts +1 -0
  108. package/build/src/components/LinkExternal/index.d.ts +1 -0
  109. package/build/src/components/Logo/Logo.d.ts +1 -0
  110. package/build/src/components/Logo/Logo.stories.d.ts +5 -0
  111. package/build/src/components/Package/Package.d.ts +1 -1
  112. package/build/src/components/Package/styles.d.ts +0 -8
  113. package/build/src/components/Person/Person.d.ts +9 -0
  114. package/build/src/components/Person/Person.test.d.ts +1 -0
  115. package/build/src/components/Person/PersonTooltip.d.ts +6 -0
  116. package/build/src/components/Person/index.d.ts +1 -0
  117. package/build/src/components/Person/utils.d.ts +3 -0
  118. package/build/src/components/Readme/Readme.d.ts +0 -1
  119. package/build/src/components/Search/AutoComplete/styles.d.ts +0 -8
  120. package/build/src/components/Search/utils.d.ts +1 -0
  121. package/build/src/components/SettingsMenu/SettingsMenu.d.ts +2 -2
  122. package/build/src/components/SettingsMenu/SettingsMenu.test.d.ts +1 -0
  123. package/build/src/components/UpLinks/UplinkLink.d.ts +6 -0
  124. package/build/src/components/Versions/Versions.d.ts +1 -0
  125. package/build/src/index.d.ts +4 -1
  126. package/build/src/sections/Detail/Tabs.d.ts +1 -0
  127. package/build/src/sections/Header/styles.d.ts +0 -7
  128. package/build/src/store/models/routes.d.ts +8 -0
  129. package/build/src/store/models/utils.d.ts +1 -0
  130. package/build/src/types/packageMeta.d.ts +7 -5
  131. package/build/src/utils/routes.d.ts +1 -0
  132. package/build/src/utils/utils.d.ts +1 -0
  133. package/build/store/models/configuration.js +2 -1
  134. package/build/store/models/login.js +4 -2
  135. package/build/store/models/manifest.js +5 -3
  136. package/build/store/models/packages.js +4 -2
  137. package/build/store/models/routes.js +18 -0
  138. package/build/store/models/search.js +4 -2
  139. package/build/store/models/utils.js +10 -0
  140. package/build/utils/routes.js +1 -0
  141. package/build/utils/utils.js +20 -1
  142. package/package.json +2 -2
  143. package/src/AppTest/AppRoute.test.tsx +65 -0
  144. package/src/Theme/ThemeProvider.test.tsx +27 -0
  145. package/src/Theme/theme.ts +3 -3
  146. package/src/components/ActionBar/ActionBar.test.tsx +36 -15
  147. package/src/components/ActionBar/ActionBar.tsx +1 -1
  148. package/src/components/ActionBar/ActionBarAction.tsx +8 -5
  149. package/src/components/Author/Author.test.tsx +7 -1
  150. package/src/components/Author/Author.tsx +3 -41
  151. package/src/components/CopyClipboard/CopyToClipBoard.test.tsx +23 -0
  152. package/src/components/CopyClipboard/utils.ts +2 -13
  153. package/src/components/Dependencies/Dependencies.tsx +9 -9
  154. package/src/components/Dependencies/DependencyBlock.tsx +2 -1
  155. package/src/components/Developers/DeveloperType.tsx +4 -0
  156. package/src/components/Developers/Developers.test.tsx +37 -10
  157. package/src/components/Developers/Developers.tsx +13 -13
  158. package/src/components/Developers/Title.tsx +1 -5
  159. package/src/components/Developers/index.ts +2 -1
  160. package/src/components/Distribution/Dist.test.tsx +1 -1
  161. package/src/components/Distribution/Dist.tsx +2 -4
  162. package/src/components/Distribution/styles.ts +0 -6
  163. package/src/components/Engines/Engines.tsx +6 -2
  164. package/src/components/Engines/styles.ts +1 -1
  165. package/src/components/ErrorBoundary/ErrorBoundary.test.tsx +39 -0
  166. package/src/components/FundButton/FundButton.tsx +5 -5
  167. package/src/components/HeaderInfoDialog/HeaderInfoDialog.test.tsx +51 -0
  168. package/src/components/HeaderInfoDialog/HeaderInfoDialog.tsx +2 -2
  169. package/src/components/Heading/Heading.test.tsx +20 -0
  170. package/src/components/Icons/DevsIcons/CommonJS.tsx +1 -7
  171. package/src/components/Icons/DevsIcons/ES6Module.tsx +2 -8
  172. package/src/components/Icons/DevsIcons/Git.tsx +1 -7
  173. package/src/components/Icons/DevsIcons/NodeJS.tsx +1 -7
  174. package/src/components/Icons/DevsIcons/TypeScript.tsx +1 -7
  175. package/src/components/Icons/FileBinary.tsx +2 -1
  176. package/src/components/Icons/Icons.stories.tsx +21 -5
  177. package/src/components/Icons/Icons.test.tsx +70 -0
  178. package/src/components/Icons/Law.tsx +2 -1
  179. package/src/components/Icons/Managers/Npm.tsx +1 -7
  180. package/src/components/Icons/Managers/Pnpm.tsx +1 -7
  181. package/src/components/Icons/Managers/Yarn.tsx +1 -7
  182. package/src/components/Install/Install.test.tsx +54 -13
  183. package/src/components/Install/Install.tsx +12 -11
  184. package/src/components/Install/InstallListItem.tsx +12 -11
  185. package/src/components/Keywords/KeywordListItems.tsx +22 -0
  186. package/src/components/Keywords/Keywords.stories.tsx +19 -0
  187. package/src/components/Keywords/Keywords.test.tsx +57 -0
  188. package/src/components/Keywords/Keywords.tsx +35 -0
  189. package/src/components/Keywords/index.ts +1 -0
  190. package/src/components/Link/Link.test.tsx +25 -0
  191. package/src/components/Link/Link.tsx +4 -18
  192. package/src/components/Link/index.ts +1 -1
  193. package/src/components/LinkExternal/LinkExternal.test.tsx +18 -0
  194. package/src/components/LinkExternal/LinkExternal.tsx +22 -0
  195. package/src/components/LinkExternal/index.ts +1 -0
  196. package/src/components/Loading/Loading.test.tsx +8 -5
  197. package/src/components/Loading/styles.ts +1 -0
  198. package/src/components/LoginDialog/LoginDialog.test.tsx +1 -1
  199. package/src/components/LoginDialog/LoginDialog.tsx +10 -1
  200. package/src/components/LoginDialog/LoginDialogCloseButton.tsx +1 -0
  201. package/src/components/LoginDialog/LoginDialogForm.tsx +0 -2
  202. package/src/components/LoginDialog/LoginDialogFormError.tsx +1 -1
  203. package/src/components/Logo/Logo.stories.tsx +16 -0
  204. package/src/components/Logo/Logo.test.tsx +8 -1
  205. package/src/components/Logo/Logo.tsx +19 -3
  206. package/src/components/Package/Package.test.tsx +47 -14
  207. package/src/components/Package/Package.tsx +41 -44
  208. package/src/components/Package/styles.ts +7 -17
  209. package/src/components/PackageList/Packagelist.test.tsx +1 -0
  210. package/src/components/Person/Person.test.tsx +50 -0
  211. package/src/components/Person/Person.tsx +45 -0
  212. package/src/components/Person/PersonTooltip.tsx +26 -0
  213. package/src/components/Person/index.ts +1 -0
  214. package/src/components/Person/utils.ts +20 -0
  215. package/src/components/RawViewer/RawViewer.tsx +8 -4
  216. package/src/components/Readme/Readme.spec.tsx +17 -0
  217. package/src/components/Readme/Readme.tsx +10 -5
  218. package/src/components/Readme/utils.ts +2 -5
  219. package/src/components/RegistryInfoDialog/styles.ts +5 -4
  220. package/src/components/Repository/Repository.tsx +9 -14
  221. package/src/components/Search/AutoComplete/styles.ts +7 -0
  222. package/src/components/Search/Search.test.tsx +36 -9
  223. package/src/components/Search/Search.tsx +4 -2
  224. package/src/components/Search/SearchItem.tsx +19 -8
  225. package/src/components/Search/utils.ts +17 -0
  226. package/src/components/SettingsMenu/SettingsMenu.test.tsx +41 -0
  227. package/src/components/SettingsMenu/SettingsMenu.tsx +48 -10
  228. package/src/components/SideBarTitle/SideBarTitle.tsx +19 -3
  229. package/src/components/UpLinks/UpLinks.test.tsx +7 -0
  230. package/src/components/UpLinks/UpLinks.tsx +38 -15
  231. package/src/components/UpLinks/UplinkLink.tsx +20 -0
  232. package/src/components/UpLinks/styles.ts +1 -0
  233. package/src/components/Versions/HistoryList.tsx +9 -4
  234. package/src/components/Versions/TagList.tsx +4 -3
  235. package/src/components/Versions/Versions.test.tsx +2 -0
  236. package/src/components/Versions/Versions.tsx +57 -32
  237. package/src/index.ts +4 -1
  238. package/src/providers/AppConfigurationProvider/AppConfigurationProvider.tsx +1 -0
  239. package/src/providers/PersistenceSettingProvider/PersistenceSettingProvider.tsx +2 -0
  240. package/src/providers/VersionProvider/VersionProvider.test.tsx +3 -3
  241. package/src/sections/Detail/Detail.test.tsx +8 -1
  242. package/src/sections/Detail/Detail.tsx +11 -4
  243. package/src/sections/Detail/Tabs.tsx +5 -2
  244. package/src/sections/Footer/Footer.tsx +15 -4
  245. package/src/sections/Footer/styles.ts +4 -0
  246. package/src/sections/Header/Header.test.tsx +12 -10
  247. package/src/sections/Header/HeaderLeft.tsx +19 -11
  248. package/src/sections/Header/HeaderMenu.tsx +1 -1
  249. package/src/sections/Header/HeaderRight.tsx +14 -3
  250. package/src/sections/Header/HeaderSettingsDialog.tsx +1 -1
  251. package/src/sections/Header/RegistryInfoContent/RegistryInfoContent.test.tsx +1 -1
  252. package/src/sections/Header/styles.ts +4 -16
  253. package/src/sections/Home/Home.test.tsx +12 -4
  254. package/src/sections/SideBar/Sidebar.test.tsx +20 -13
  255. package/src/sections/SideBar/Sidebar.tsx +5 -9
  256. package/src/store/api.test.ts +16 -0
  257. package/src/store/models/configuration.ts +2 -1
  258. package/src/store/models/login.ts +10 -12
  259. package/src/store/models/manifest.ts +6 -5
  260. package/src/store/models/packages.ts +4 -5
  261. package/src/store/models/routes.ts +10 -0
  262. package/src/store/models/search.ts +4 -2
  263. package/src/store/models/utils.ts +3 -0
  264. package/src/types/packageMeta.ts +7 -5
  265. package/src/utils/routes.ts +1 -0
  266. package/src/utils/utils.test.ts +34 -0
  267. package/src/utils/utils.ts +20 -5
  268. package/tsconfig.json +1 -1
  269. package/build/components/Developers/styles.js +0 -65
  270. package/build/components/Distribution/utils.js +0 -25
  271. package/build/components/Distribution/utilts.spec.js +0 -18
  272. package/build/components/Package/Tag/Tag.js +0 -14
  273. package/build/components/Package/Tag/styles.js +0 -24
  274. package/build/sections/Header/RegistryInfoDialog/RegistryInfoDialog.js +0 -36
  275. package/build/sections/Header/RegistryInfoDialog/styles.js +0 -46
  276. package/build/sections/Header/RegistryInfoDialog/types.js +0 -6
  277. package/build/src/components/Developers/styles.d.ts +0 -11
  278. package/build/src/components/Distribution/utils.d.ts +0 -7
  279. package/build/src/components/Package/Tag/Tag.d.ts +0 -6
  280. package/build/src/components/Package/Tag/index.d.ts +0 -1
  281. package/build/src/components/Package/Tag/styles.d.ts +0 -5
  282. package/build/src/sections/Header/RegistryInfoDialog/RegistryInfoDialog.d.ts +0 -4
  283. package/build/src/sections/Header/RegistryInfoDialog/index.d.ts +0 -1
  284. package/build/src/sections/Header/RegistryInfoDialog/styles.d.ts +0 -13
  285. package/build/src/sections/Header/RegistryInfoDialog/types.d.ts +0 -7
  286. package/src/components/Developers/styles.ts +0 -31
  287. package/src/components/Distribution/utils.ts +0 -32
  288. package/src/components/Distribution/utilts.spec.ts +0 -17
  289. package/src/components/Package/Tag/Tag.test.tsx +0 -15
  290. package/src/components/Package/Tag/Tag.tsx +0 -11
  291. package/src/components/Package/Tag/index.ts +0 -1
  292. package/src/components/Package/Tag/styles.ts +0 -11
  293. package/src/components/Search/AutoComplete/styles.tsx +0 -42
  294. package/src/sections/Header/RegistryInfoDialog/RegistryInfoDialog.tsx +0 -31
  295. package/src/sections/Header/RegistryInfoDialog/index.ts +0 -1
  296. package/src/sections/Header/RegistryInfoDialog/styles.ts +0 -21
  297. package/src/sections/Header/RegistryInfoDialog/types.ts +0 -8
  298. /package/build/components/Icons/DevsIcons/{es6modules.svg → es6module.svg} +0 -0
  299. /package/build/src/{components/Package/Tag/Tag.test.d.ts → AppTest/AppRoute.test.d.ts} +0 -0
  300. /package/src/components/Icons/DevsIcons/{es6modules.svg → es6module.svg} +0 -0
@@ -1,8 +1,6 @@
1
1
  import styled from '@emotion/styled';
2
2
  import { Typography } from '@mui/material';
3
- import Grid from '@mui/material/Grid';
4
3
  import List from '@mui/material/List';
5
- import { useTheme } from '@mui/styles';
6
4
  import React from 'react';
7
5
  import { useTranslation } from 'react-i18next';
8
6
 
@@ -18,6 +16,12 @@ const StyledText = styled(Typography)<{ theme?: Theme }>((props) => ({
18
16
  textTransform: 'capitalize',
19
17
  }));
20
18
 
19
+ const Wrapper = styled('div')({
20
+ display: 'flex',
21
+ alignItems: 'center',
22
+ justifyContent: 'space-between',
23
+ });
24
+
21
25
  export type Props = {
22
26
  packageMeta: PackageMetaInterface;
23
27
  packageName: string;
@@ -26,7 +30,6 @@ export type Props = {
26
30
 
27
31
  const Install: React.FC<Props> = ({ packageMeta, packageName, configOptions }) => {
28
32
  const { t } = useTranslation();
29
- const theme = useTheme();
30
33
  if (!packageMeta || !packageName) {
31
34
  return null;
32
35
  }
@@ -38,16 +41,14 @@ const Install: React.FC<Props> = ({ packageMeta, packageName, configOptions }) =
38
41
 
39
42
  return hasPkgManagers ? (
40
43
  <>
41
- <Grid
42
- container={true}
43
- justifyContent="flex-end"
44
- sx={{ marginRight: theme.spacing(10), alingText: 'right' }}
45
- >
46
- <SettingsMenu packageName={packageName} />
47
- </Grid>
48
44
  <List
49
45
  data-testid={'installList'}
50
- subheader={<StyledText variant={'subtitle1'}>{t('sidebar.installation.title')}</StyledText>}
46
+ subheader={
47
+ <Wrapper>
48
+ <StyledText variant={'subtitle1'}>{t('sidebar.installation.title')}</StyledText>
49
+ <SettingsMenu packageName={packageName} />
50
+ </Wrapper>
51
+ }
51
52
  >
52
53
  {hasNpm && (
53
54
  <InstallListItem
@@ -22,9 +22,9 @@ const InstallListItemText = styled(ListItemText)({
22
22
  });
23
23
 
24
24
  const PackageMangerAvatar = styled(Avatar)({
25
- borderRadius: '0px',
26
25
  backgroundColor: 'transparent',
27
26
  padding: 0,
27
+ marginLeft: 0,
28
28
  });
29
29
 
30
30
  export enum DependencyManager {
@@ -39,10 +39,10 @@ interface Interface {
39
39
  packageVersion?: string;
40
40
  }
41
41
 
42
- export function getGlobalInstall(isGlobal, packageVersion, packageName, isYarn = false) {
42
+ export function getGlobalInstall(isLatest, isGlobal, packageVersion, packageName, isYarn = false) {
43
43
  const name = isGlobal
44
- ? `${isYarn ? '' : '-g'} ${packageVersion ? `${packageName}@${packageVersion}` : packageName}`
45
- : packageVersion
44
+ ? `${isYarn ? '' : '-g'} ${packageVersion && !isLatest ? `${packageName}@${packageVersion}` : packageName}`
45
+ : packageVersion && !isLatest
46
46
  ? `${packageName}@${packageVersion}`
47
47
  : packageName;
48
48
 
@@ -56,6 +56,7 @@ const InstallListItem: React.FC<Interface> = ({
56
56
  }) => {
57
57
  const { localSettings } = useSettings();
58
58
  const theme = useTheme();
59
+ const isLatest = localSettings[packageName]?.latest ?? false;
59
60
  const isGlobal = localSettings[packageName]?.global ?? false;
60
61
  switch (dependencyManager) {
61
62
  case DependencyManager.NPM:
@@ -67,9 +68,9 @@ const InstallListItem: React.FC<Interface> = ({
67
68
  <InstallListItemText
68
69
  primary={
69
70
  <CopyToClipBoard
70
- dataTestId="instalNpm"
71
- text={`npm install ${getGlobalInstall(isGlobal, packageVersion, packageName)}`}
72
- title={`npm install ${getGlobalInstall(isGlobal, packageVersion, packageName)}`}
71
+ dataTestId="installNpm"
72
+ text={`npm install ${getGlobalInstall(isLatest, isGlobal, packageVersion, packageName)}`}
73
+ title={`npm install ${getGlobalInstall(isLatest, isGlobal, packageVersion, packageName)}`}
73
74
  />
74
75
  }
75
76
  />
@@ -93,7 +94,7 @@ const InstallListItem: React.FC<Interface> = ({
93
94
  packageName,
94
95
  true
95
96
  )}`
96
- : `yarn add ${getGlobalInstall(isGlobal, packageVersion, packageName, true)}`
97
+ : `yarn add ${getGlobalInstall(isLatest, isGlobal, packageVersion, packageName, true)}`
97
98
  }
98
99
  title={
99
100
  isGlobal
@@ -103,7 +104,7 @@ const InstallListItem: React.FC<Interface> = ({
103
104
  packageName,
104
105
  true
105
106
  )}`
106
- : `yarn add ${getGlobalInstall(isGlobal, packageVersion, packageName, true)}`
107
+ : `yarn add ${getGlobalInstall(isLatest, isGlobal, packageVersion, packageName, true)}`
107
108
  }
108
109
  />
109
110
  }
@@ -120,8 +121,8 @@ const InstallListItem: React.FC<Interface> = ({
120
121
  primary={
121
122
  <CopyToClipBoard
122
123
  dataTestId="installPnpm"
123
- text={`pnpm install ${getGlobalInstall(isGlobal, packageVersion, packageName)}`}
124
- title={`pnpm install ${getGlobalInstall(isGlobal, packageVersion, packageName)}`}
124
+ text={`pnpm install ${getGlobalInstall(isLatest, isGlobal, packageVersion, packageName)}`}
125
+ title={`pnpm install ${getGlobalInstall(isLatest, isGlobal, packageVersion, packageName)}`}
125
126
  />
126
127
  }
127
128
  />
@@ -0,0 +1,22 @@
1
+ import Chip from '@mui/material/Chip';
2
+ import ListItem from '@mui/material/ListItem';
3
+ import React from 'react';
4
+
5
+ const KeywordListItems: React.FC<{ keywords: undefined | string | string[] }> = ({ keywords }) => {
6
+ const keywordList =
7
+ typeof keywords === 'string' ? keywords.replace(/,/g, ' ').split(' ') : keywords;
8
+
9
+ if (!keywordList) {
10
+ return null;
11
+ }
12
+
13
+ return (
14
+ <ListItem sx={{ px: 0, mt: 0, flexWrap: 'wrap' }}>
15
+ {keywordList.sort().map((keyword, index) => (
16
+ <Chip key={index} label={keyword} sx={{ mt: 1, mr: 1 }} />
17
+ ))}
18
+ </ListItem>
19
+ );
20
+ };
21
+
22
+ export default KeywordListItems;
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+
3
+ import { default as Keywords } from '.';
4
+
5
+ export default {
6
+ title: 'Components/Sidebar/Keywords',
7
+ };
8
+
9
+ export const AllProperties: any = () => (
10
+ <Keywords
11
+ packageMeta={{
12
+ latest: {
13
+ name: 'verdaccio1',
14
+ version: '4.0.0',
15
+ keywords: ['verdaccio', 'npm', 'yarn'],
16
+ },
17
+ }}
18
+ />
19
+ );
@@ -0,0 +1,57 @@
1
+ import React from 'react';
2
+
3
+ import { render, screen } from '../../test/test-react-testing-library';
4
+ import Keywords from './Keywords';
5
+
6
+ describe('<Keywords /> component', () => {
7
+ test('should render the component in default state', () => {
8
+ const packageMeta = {
9
+ latest: {
10
+ name: 'verdaccio1',
11
+ version: '4.0.0',
12
+ keywords: ['verdaccio', 'npm', 'yarn'],
13
+ },
14
+ };
15
+
16
+ const container = render(<Keywords packageMeta={packageMeta} />);
17
+
18
+ expect(container.getByText('sidebar.keywords.title')).toBeInTheDocument();
19
+ expect(container.getByText('verdaccio')).toBeInTheDocument();
20
+ expect(container.getByText('npm')).toBeInTheDocument();
21
+ expect(container.getByText('yarn')).toBeInTheDocument();
22
+ });
23
+
24
+ test('should not render if data is missing', () => {
25
+ // @ts-ignore
26
+ render(<Keywords packageMeta={{}} />);
27
+ expect(screen.queryByTestId('keyword-list')).toBeNull();
28
+
29
+ const packageMeta = {
30
+ latest: {
31
+ name: 'verdaccio1',
32
+ version: '4.0.0',
33
+ keywords: '',
34
+ },
35
+ };
36
+
37
+ render(<Keywords packageMeta={packageMeta} />);
38
+ expect(screen.queryByTestId('keyword-list')).toBeNull();
39
+ });
40
+
41
+ test('should render keywords set in string', () => {
42
+ const packageMeta = {
43
+ latest: {
44
+ name: 'verdaccio1',
45
+ version: '4.0.0',
46
+ keywords: 'hello, world, verdaccio',
47
+ },
48
+ };
49
+
50
+ const container = render(<Keywords packageMeta={packageMeta} />);
51
+
52
+ expect(container.getByText('sidebar.keywords.title')).toBeInTheDocument();
53
+ expect(container.getByText('verdaccio')).toBeInTheDocument();
54
+ expect(container.getByText('hello')).toBeInTheDocument();
55
+ expect(container.getByText('world')).toBeInTheDocument();
56
+ });
57
+ });
@@ -0,0 +1,35 @@
1
+ import List from '@mui/material/List';
2
+ import Typography from '@mui/material/Typography';
3
+ import { useTheme } from '@mui/styles';
4
+ import React from 'react';
5
+ import { useTranslation } from 'react-i18next';
6
+
7
+ import { PackageMetaInterface } from '../../types/packageMeta';
8
+ import KeywordListItems from './KeywordListItems';
9
+
10
+ const Keywords: React.FC<{ packageMeta: PackageMetaInterface }> = ({ packageMeta }) => {
11
+ const { t } = useTranslation();
12
+ const theme = useTheme();
13
+
14
+ if (!packageMeta?.latest?.keywords) {
15
+ return null;
16
+ }
17
+
18
+ return (
19
+ <List
20
+ data-testid="keyword-list"
21
+ subheader={
22
+ <Typography
23
+ sx={{ fontWeight: theme.fontWeight.bold, textTransform: 'capitalize' }}
24
+ variant="subtitle1"
25
+ >
26
+ {t('sidebar.keywords.title')}
27
+ </Typography>
28
+ }
29
+ >
30
+ <KeywordListItems keywords={packageMeta?.latest?.keywords} />
31
+ </List>
32
+ );
33
+ };
34
+
35
+ export default Keywords;
@@ -0,0 +1 @@
1
+ export { default } from './Keywords';
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ import { BrowserRouter as Router } from 'react-router-dom';
3
+
4
+ import { render } from '../../test/test-react-testing-library';
5
+ import Link from './Link';
6
+
7
+ describe('<Link /> component', () => {
8
+ test('should render the component in default state', () => {
9
+ const { container } = render(
10
+ <Router>
11
+ <Link to={'/'} />
12
+ </Router>
13
+ );
14
+ expect(container.firstChild).toMatchSnapshot();
15
+ });
16
+
17
+ test('should render the component with link', () => {
18
+ const { container } = render(
19
+ <Router>
20
+ <Link to={'/'}>{'Home'}</Link>
21
+ </Router>
22
+ );
23
+ expect(container.firstChild).toMatchSnapshot();
24
+ });
25
+ });
@@ -3,9 +3,7 @@ import Typography from '@mui/material/Typography';
3
3
  import React from 'react';
4
4
  import { Link as RouterLink } from 'react-router-dom';
5
5
 
6
- type LinkRef = HTMLAnchorElement;
7
-
8
- export const CustomRouterLink = styled(RouterLink)`
6
+ const CustomRouterLink = styled(RouterLink)`
9
7
  text-decoration: none;
10
8
  &:hover,
11
9
  &:focus {
@@ -13,23 +11,11 @@ export const CustomRouterLink = styled(RouterLink)`
13
11
  }
14
12
  `;
15
13
 
16
- // TODO: improve any with custom types for a and RouterLink
17
- const Link = React.forwardRef<LinkRef, any>(function LinkFunction(
18
- { external, to, children, variant, className, onClick },
14
+ const Link = React.forwardRef<HTMLAnchorElement, any>(function LinkFunction(
15
+ { to, children, variant, className, onClick },
19
16
  ref
20
17
  ) {
21
- return external ? (
22
- <a
23
- className={className}
24
- href={to}
25
- onClick={onClick}
26
- ref={ref}
27
- rel="noopener noreferrer"
28
- target="_blank"
29
- >
30
- <Typography variant={variant ?? 'caption'}>{children}</Typography>
31
- </a>
32
- ) : (
18
+ return (
33
19
  <CustomRouterLink className={className} innerRef={ref} onClick={onClick} to={to}>
34
20
  <Typography variant={variant}>{children}</Typography>
35
21
  </CustomRouterLink>
@@ -1 +1 @@
1
- export { default as Link } from './Link';
1
+ export { default } from './Link';
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+
3
+ import { render } from '../../test/test-react-testing-library';
4
+ import LinkExternal from './LinkExternal';
5
+
6
+ describe('<LinkExternal /> component', () => {
7
+ test('should render the component in default state', () => {
8
+ const { container } = render(<LinkExternal to={'/'} />);
9
+ expect(container.firstChild).toMatchSnapshot();
10
+ });
11
+
12
+ test('should render the component with external link', () => {
13
+ const { container } = render(
14
+ <LinkExternal to={'https://example.com'}>{'Example'}</LinkExternal>
15
+ );
16
+ expect(container.firstChild).toMatchSnapshot();
17
+ });
18
+ });
@@ -0,0 +1,22 @@
1
+ import Link from '@mui/material/Link';
2
+ import React from 'react';
3
+
4
+ const LinkExternal = React.forwardRef<HTMLAnchorElement, any>((props, ref) => {
5
+ const { to, children, variant, ...rest } = props;
6
+ return (
7
+ // eslint-disable-next-line verdaccio/jsx-spread
8
+ <Link
9
+ href={to}
10
+ ref={ref}
11
+ rel="noopener noreferrer"
12
+ target="_blank"
13
+ underline="hover"
14
+ variant={variant ?? 'caption'}
15
+ {...rest}
16
+ >
17
+ {children}
18
+ </Link>
19
+ );
20
+ });
21
+
22
+ export default LinkExternal;
@@ -0,0 +1 @@
1
+ export { default } from './LinkExternal';
@@ -1,12 +1,15 @@
1
1
  import React from 'react';
2
2
 
3
- import { render, screen } from '../../test/test-react-testing-library';
3
+ import { act, render, screen, waitFor } from '../../test/test-react-testing-library';
4
4
  import Loading from './Loading';
5
5
 
6
6
  describe('<Loading /> component', () => {
7
- test('should render the component in default state', () => {
8
- render(<Loading />);
9
- screen.debug();
10
- expect(screen.getByTestId('loading')).toBeInTheDocument();
7
+ test('should render the component in default state', async () => {
8
+ act(() => {
9
+ render(<Loading />);
10
+ });
11
+ await waitFor(() => {
12
+ expect(screen.getByTestId('loading')).toBeInTheDocument();
13
+ });
11
14
  });
12
15
  });
@@ -11,6 +11,7 @@ export const Wrapper = styled('div')({
11
11
 
12
12
  export const Badge = styled('div')<{ theme?: Theme }>(({ theme }) => ({
13
13
  margin: '0 0 30px 0',
14
+ padding: 5,
14
15
  borderRadius: 25,
15
16
  boxShadow: '0 10px 20px 0 rgba(69, 58, 100, 0.2)',
16
17
  background: theme?.palette.mode === 'dark' ? theme?.palette.black : '#f7f8f6',
@@ -87,7 +87,7 @@ describe('<LoginDialog /> component', () => {
87
87
  fireEvent.change(userNameInput, { target: { value: 'xyz' } });
88
88
 
89
89
  const passwordInput = screen.getByPlaceholderText('form-placeholder.password');
90
- expect(userNameInput).toBeInTheDocument();
90
+ expect(passwordInput).toBeInTheDocument();
91
91
  fireEvent.focus(passwordInput);
92
92
 
93
93
  await act(async () => {
@@ -21,7 +21,7 @@ const LoginDialog: React.FC<Props> = ({ onClose, open = false }) => {
21
21
  const makeLogin = useCallback(
22
22
  async (username?: string, password?: string): Promise<LoginBody | void> => {
23
23
  // checks isEmpty
24
- if (isEmpty(username) || isEmpty(password)) {
24
+ if (!username || !password || isEmpty(username) || isEmpty(password)) {
25
25
  dispatch.login.addError({
26
26
  type: 'error',
27
27
  description: i18next.t('form-validation.username-or-password-cant-be-empty'),
@@ -29,6 +29,15 @@ const LoginDialog: React.FC<Props> = ({ onClose, open = false }) => {
29
29
  return;
30
30
  }
31
31
 
32
+ // checks min username and password length
33
+ if (username.length < 2 || password.length < 2) {
34
+ dispatch.login.addError({
35
+ type: 'error',
36
+ description: i18next.t('form-validation.required-min-length', { length: 2 }),
37
+ });
38
+ return;
39
+ }
40
+
32
41
  try {
33
42
  dispatch.login.getUser({ username, password });
34
43
  // const response: LoginBody = await doLogin(username as string, password as string);
@@ -12,6 +12,7 @@ const StyledIconButton = styled(IconButton)<{ theme?: Theme }>(({ theme }) => ({
12
12
  right: theme.spacing() / 2,
13
13
  top: theme.spacing() / 2,
14
14
  color: theme.palette.grey[500],
15
+ zIndex: 99,
15
16
  }));
16
17
 
17
18
  interface Props {
@@ -48,7 +48,6 @@ const LoginDialogForm = memo(({ onSubmit, error }: Props) => {
48
48
  id="login--dialog-username"
49
49
  {...register('username', {
50
50
  required: { value: true, message: t('form-validation.required-field') },
51
- minLength: { value: 2, message: t('form-validation.required-min-length', { length: 2 }) },
52
51
  })}
53
52
  label={t('form.username')}
54
53
  margin="normal"
@@ -65,7 +64,6 @@ const LoginDialogForm = memo(({ onSubmit, error }: Props) => {
65
64
  id="login--dialog-password"
66
65
  {...register('password', {
67
66
  required: { value: true, message: t('form-validation.required-field') },
68
- minLength: { value: 2, message: t('form-validation.required-min-length', { length: 2 }) },
69
67
  })}
70
68
  data-testid="password"
71
69
  label={t('form.password')}
@@ -30,7 +30,7 @@ const LoginDialogFormError = memo(({ error }: Props) => {
30
30
  return (
31
31
  <StyledSnackbarContent
32
32
  message={
33
- <Box alignItems="center" display="flex">
33
+ <Box alignItems="center" data-testid="error" display="flex">
34
34
  <StyledErrorIcon />
35
35
  {error.description}
36
36
  </Box>
@@ -0,0 +1,16 @@
1
+ import Box from '@mui/material/Box';
2
+ import React from 'react';
3
+
4
+ import Logo from './Logo';
5
+
6
+ export default {
7
+ title: 'Components/Logo',
8
+ };
9
+
10
+ export const Icons: any = () => (
11
+ <Box sx={{ width: '100%' }}>
12
+ <Logo size="x-small" />
13
+ <Logo size="small" />
14
+ <Logo size="big" />
15
+ </Box>
16
+ );
@@ -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 Logo from './Logo';
5
5
 
6
6
  describe('<Logo /> component', () => {
7
7
  test('should render the component in default state', () => {
8
8
  const { container } = render(<Logo />);
9
9
  expect(container.firstChild).toMatchSnapshot();
10
+ expect(screen.getByTestId('default-logo')).toBeTruthy();
11
+ });
12
+
13
+ test('should render custom logo', () => {
14
+ window.__VERDACCIO_BASENAME_UI_OPTIONS.logo = 'custom.png';
15
+ render(<Logo />);
16
+ expect(screen.getByTestId('custom-logo')).toBeTruthy();
10
17
  });
11
18
  });
@@ -1,4 +1,5 @@
1
1
  import styled from '@emotion/styled';
2
+ import { useTheme } from '@mui/styles';
2
3
  import React from 'react';
3
4
 
4
5
  import { Theme, useConfig } from '../../';
@@ -22,18 +23,33 @@ interface Props {
22
23
  onClick?: () => void;
23
24
  className?: string;
24
25
  isDefault?: boolean;
26
+ title?: string;
25
27
  }
26
28
 
27
- const Logo: React.FC<Props> = ({ size, onClick, className, isDefault = false }) => {
29
+ const Logo: React.FC<Props> = ({ size, onClick, className, isDefault = false, title = '' }) => {
28
30
  const { configOptions } = useConfig();
31
+ const theme = useTheme();
29
32
  if (!isDefault && configOptions?.logo) {
33
+ const logoSrc =
34
+ theme?.palette.mode === 'dark' && configOptions.logoDark
35
+ ? configOptions.logoDark
36
+ : configOptions.logo;
30
37
  return (
31
38
  <ImageLogo className={className} onClick={onClick}>
32
- <img alt="logo" height="40px" src={configOptions.logo} />
39
+ <img alt={title} data-testid={'custom-logo'} height="40px" src={logoSrc} />
33
40
  </ImageLogo>
34
41
  );
35
42
  }
36
- return <StyledLogo className={className} onClick={onClick} size={size} />;
43
+
44
+ return (
45
+ <StyledLogo
46
+ className={className}
47
+ data-testid={'default-logo'}
48
+ onClick={onClick}
49
+ size={size}
50
+ title={title}
51
+ />
52
+ );
37
53
  };
38
54
 
39
55
  export default Logo;
@@ -2,7 +2,13 @@ import React from 'react';
2
2
  import { MemoryRouter } from 'react-router';
3
3
 
4
4
  import { store } from '../../';
5
- import { cleanup, renderWithStore } from '../../test/test-react-testing-library';
5
+ import {
6
+ cleanup,
7
+ fireEvent,
8
+ renderWithStore,
9
+ screen,
10
+ waitFor,
11
+ } from '../../test/test-react-testing-library';
6
12
  import Package from './Package';
7
13
 
8
14
  /**
@@ -11,29 +17,36 @@ import Package from './Package';
11
17
  */
12
18
  const dateOneMonthAgo = (): Date => new Date(1544377770747);
13
19
 
20
+ const props = {
21
+ name: 'verdaccio',
22
+ version: '1.0.0',
23
+ time: String(dateOneMonthAgo()),
24
+ license: 'MIT',
25
+ description: 'Private NPM repository',
26
+ author: {
27
+ name: 'Sam',
28
+ },
29
+ dist: {
30
+ fileCount: 1,
31
+ unpackedSize: 171,
32
+ tarball: 'http://localhost:9000/verdaccio/-/verdaccio-1.0.0.tgz',
33
+ },
34
+ keywords: ['verdaccio-core'],
35
+ };
36
+
14
37
  describe('<Package /> component', () => {
15
38
  afterEach(() => {
16
39
  cleanup();
17
40
  });
18
41
 
19
42
  test('should load the component', () => {
20
- const props = {
21
- name: 'verdaccio',
22
- version: '1.0.0',
23
- time: String(dateOneMonthAgo()),
24
- license: 'MIT',
25
- description: 'Private NPM repository',
26
- author: {
27
- name: 'Sam',
28
- },
29
- keywords: ['verdaccio'],
30
- };
31
-
32
43
  const wrapper = renderWithStore(
33
44
  <MemoryRouter>
34
45
  <Package
35
46
  author={props.author}
36
47
  description={props.description}
48
+ dist={props.dist}
49
+ keywords={props.keywords}
37
50
  license={props.license}
38
51
  name={props.name}
39
52
  time={props.time}
@@ -50,5 +63,25 @@ describe('<Package /> component', () => {
50
63
  expect(wrapper.getByText('MIT')).toBeInTheDocument();
51
64
  });
52
65
 
53
- test.todo('should load the component without author');
66
+ // test if click on download button will trigger the download action
67
+ test('should download the package', async () => {
68
+ renderWithStore(
69
+ <MemoryRouter>
70
+ <Package
71
+ author={props.author}
72
+ description={props.description}
73
+ dist={props.dist}
74
+ keywords={props.keywords}
75
+ license={props.license}
76
+ name={props.name}
77
+ time={props.time}
78
+ version={props.version}
79
+ />
80
+ </MemoryRouter>,
81
+ store
82
+ );
83
+
84
+ fireEvent.click(screen.getByTestId('download-tarball'));
85
+ await waitFor(() => expect(store.getState().loading.models.download).toBe(true));
86
+ });
54
87
  });