@strapi/admin 4.0.0-next.15 → 4.0.0-next.16

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 (161) hide show
  1. package/admin/src/components/AutoReloadOverlayBlockerProvider/Blocker.js +56 -24
  2. package/admin/src/components/AutoReloadOverlayBlockerProvider/Overlay.js +3 -15
  3. package/admin/src/components/AutoReloadOverlayBlockerProvider/index.js +6 -6
  4. package/admin/src/components/LeftMenu/index.js +91 -16
  5. package/admin/src/content-manager/components/DynamicTable/CellContent/Media/FileWrapper.js +3 -17
  6. package/admin/src/content-manager/components/Inputs/index.js +4 -1
  7. package/admin/src/content-manager/components/SelectWrapper/index.js +4 -1
  8. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +5 -2
  9. package/admin/src/pages/AuthPage/components/ForgotPassword/index.js +2 -2
  10. package/admin/src/pages/AuthPage/components/Login/BaseLogin.js +1 -1
  11. package/admin/src/pages/AuthPage/components/Register/index.js +1 -1
  12. package/admin/src/pages/HomePage/ContentBlocks.js +5 -1
  13. package/admin/src/pages/HomePage/SocialLinks.js +62 -6
  14. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ConditionsModal/index.js +2 -2
  15. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypeCollapse/Collapse/index.js +6 -2
  16. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/ContentTypes/index.js +2 -1
  17. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/RoleForm/index.js +3 -13
  18. package/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js +2 -2
  19. package/admin/src/translations/ar.json +0 -15
  20. package/admin/src/translations/cs.json +0 -23
  21. package/admin/src/translations/de.json +0 -34
  22. package/admin/src/translations/dk.json +0 -33
  23. package/admin/src/translations/en.json +80 -79
  24. package/admin/src/translations/es.json +0 -30
  25. package/admin/src/translations/fr.json +0 -26
  26. package/admin/src/translations/he.json +0 -18
  27. package/admin/src/translations/id.json +0 -29
  28. package/admin/src/translations/it.json +0 -34
  29. package/admin/src/translations/ja.json +0 -22
  30. package/admin/src/translations/ko.json +0 -20
  31. package/admin/src/translations/ms.json +0 -26
  32. package/admin/src/translations/nl.json +0 -17
  33. package/admin/src/translations/no.json +0 -18
  34. package/admin/src/translations/pl.json +0 -28
  35. package/admin/src/translations/pt-BR.json +0 -20
  36. package/admin/src/translations/pt.json +0 -21
  37. package/admin/src/translations/ru.json +0 -33
  38. package/admin/src/translations/sk.json +0 -28
  39. package/admin/src/translations/sv.json +0 -2
  40. package/admin/src/translations/th.json +0 -28
  41. package/admin/src/translations/tr.json +0 -18
  42. package/admin/src/translations/uk.json +0 -25
  43. package/admin/src/translations/vi.json +0 -20
  44. package/admin/src/translations/zh-Hans.json +0 -24
  45. package/admin/src/translations/zh.json +0 -15
  46. package/build/1920.6f7ee484.chunk.js +1 -0
  47. package/build/2321.0bd82db2.chunk.js +1 -0
  48. package/build/3736.e4c31780.chunk.js +1 -0
  49. package/build/3742.7cb60b42.chunk.js +1 -0
  50. package/build/5381.572f0c02.chunk.js +1 -0
  51. package/build/5935.dd43c971.chunk.js +2 -0
  52. package/build/5935.dd43c971.chunk.js.LICENSE.txt +14 -0
  53. package/build/6317.574fe2fa.chunk.js +2 -0
  54. package/build/6317.574fe2fa.chunk.js.LICENSE.txt +15 -0
  55. package/build/6505.d132ab1b.chunk.js +1 -0
  56. package/build/8089.d60269e4.chunk.js +1 -0
  57. package/build/9572.3e00ebbb.chunk.js +1 -0
  58. package/build/9626.21391f2a.chunk.js +1 -0
  59. package/build/9662.f9dc41c4.chunk.js +1 -0
  60. package/build/9669.15e70c2f.chunk.js +1 -0
  61. package/build/Admin-authenticatedApp.eeb514c9.chunk.js +1 -0
  62. package/build/Admin_homePage.8a4dcfaa.chunk.js +1 -0
  63. package/build/Admin_marketplace.2c239cd9.chunk.js +1 -0
  64. package/build/Admin_pluginsPage.fe1587a6.chunk.js +1 -0
  65. package/build/Admin_settingsPage.303c83d5.chunk.js +1 -0
  66. package/build/admin-edit-roles-page.eb718f56.chunk.js +1 -0
  67. package/build/ar-json.f9cb55b0.chunk.js +1 -0
  68. package/build/content-manager.8219dae0.chunk.js +1 -0
  69. package/build/cs-json.13271b78.chunk.js +1 -0
  70. package/build/de-json.79a51add.chunk.js +1 -0
  71. package/build/dk-json.c65ffcc3.chunk.js +1 -0
  72. package/build/documentation-page.84f380a7.chunk.js +1 -0
  73. package/build/documentation-translation-zh-Hans-json.e53d0c79.chunk.js +1 -0
  74. package/build/email-settings-page.cb22fda9.chunk.js +1 -0
  75. package/build/email-translation-ar-json.536b0217.chunk.js +1 -0
  76. package/build/email-translation-cs-json.8f533c9b.chunk.js +1 -0
  77. package/build/email-translation-de-json.89f5373e.chunk.js +1 -0
  78. package/build/email-translation-dk-json.9c95cf96.chunk.js +1 -0
  79. package/build/email-translation-en-json.5ec38fe9.chunk.js +1 -0
  80. package/build/email-translation-es-json.fec78330.chunk.js +1 -0
  81. package/build/email-translation-fr-json.76afb1c3.chunk.js +1 -0
  82. package/build/email-translation-id-json.1b3e055a.chunk.js +1 -0
  83. package/build/email-translation-it-json.7273fee2.chunk.js +1 -0
  84. package/build/email-translation-ja-json.b75afc52.chunk.js +1 -0
  85. package/build/email-translation-ko-json.eb9a23cd.chunk.js +1 -0
  86. package/build/email-translation-ms-json.af7c5861.chunk.js +1 -0
  87. package/build/email-translation-nl-json.10fec023.chunk.js +1 -0
  88. package/build/email-translation-pl-json.ebda42d5.chunk.js +1 -0
  89. package/build/email-translation-pt-BR-json.338d8b7c.chunk.js +1 -0
  90. package/build/email-translation-pt-json.1cd0fedf.chunk.js +1 -0
  91. package/build/email-translation-ru-json.2c369331.chunk.js +1 -0
  92. package/build/email-translation-sk-json.ba2e026d.chunk.js +1 -0
  93. package/build/email-translation-th-json.16457076.chunk.js +1 -0
  94. package/build/email-translation-tr-json.92e0a5d9.chunk.js +1 -0
  95. package/build/email-translation-uk-json.d00dd5b1.chunk.js +1 -0
  96. package/build/email-translation-vi-json.ed425dde.chunk.js +1 -0
  97. package/build/email-translation-zh-Hans-json.e2c630b6.chunk.js +1 -0
  98. package/build/email-translation-zh-json.2a06ebac.chunk.js +1 -0
  99. package/build/en-json.b4b93170.chunk.js +1 -0
  100. package/build/es-json.f5f967b8.chunk.js +1 -0
  101. package/build/fr-json.f53cb20f.chunk.js +1 -0
  102. package/build/he-json.ef9db0b0.chunk.js +1 -0
  103. package/build/i18n-translation-en-json.17af559c.chunk.js +1 -0
  104. package/build/i18n-translation-zh-Hans-json.670b4940.chunk.js +1 -0
  105. package/build/id-json.444fb2bc.chunk.js +1 -0
  106. package/build/index.html +1 -1
  107. package/build/it-json.d096e255.chunk.js +1 -0
  108. package/build/ja-json.7ddf0d03.chunk.js +1 -0
  109. package/build/ko-json.d567bad9.chunk.js +1 -0
  110. package/build/main.f54a69d1.js +2 -0
  111. package/build/main.f54a69d1.js.LICENSE.txt +120 -0
  112. package/build/ms-json.877857c6.chunk.js +1 -0
  113. package/build/nl-json.53a278ac.chunk.js +1 -0
  114. package/build/no-json.253312ce.chunk.js +1 -0
  115. package/build/pl-json.f949cbf1.chunk.js +1 -0
  116. package/build/pt-BR-json.16a743f0.chunk.js +1 -0
  117. package/build/pt-json.b9c55575.chunk.js +1 -0
  118. package/build/ru-json.3a833400.chunk.js +1 -0
  119. package/build/runtime~main.33a02236.js +1 -0
  120. package/build/sk-json.e7672f7e.chunk.js +1 -0
  121. package/build/sv-json.a2c408b3.chunk.js +1 -0
  122. package/build/th-json.6de26f39.chunk.js +1 -0
  123. package/build/tr-json.07b54f78.chunk.js +1 -0
  124. package/build/uk-json.36a7841e.chunk.js +1 -0
  125. package/build/upload-settings.9900e97b.chunk.js +1 -0
  126. package/build/upload-translation-en-json.555efcc4.chunk.js +1 -0
  127. package/build/upload-translation-zh-Hans-json.79473d61.chunk.js +1 -0
  128. package/build/upload.676c3cbd.chunk.js +1 -0
  129. package/build/users-advanced-settings-page.26c25559.chunk.js +1 -0
  130. package/build/users-permissions-translation-ar-json.6fe0dcf5.chunk.js +1 -0
  131. package/build/users-permissions-translation-cs-json.dd4bb452.chunk.js +1 -0
  132. package/build/users-permissions-translation-de-json.1505b462.chunk.js +1 -0
  133. package/build/users-permissions-translation-dk-json.6b47229f.chunk.js +1 -0
  134. package/build/users-permissions-translation-en-json.3e650c44.chunk.js +1 -0
  135. package/build/users-permissions-translation-es-json.768cc00e.chunk.js +1 -0
  136. package/build/users-permissions-translation-fr-json.12f3c930.chunk.js +1 -0
  137. package/build/users-permissions-translation-id-json.ec3deaf0.chunk.js +1 -0
  138. package/build/users-permissions-translation-it-json.baa4f859.chunk.js +1 -0
  139. package/build/users-permissions-translation-ja-json.3ddd4418.chunk.js +1 -0
  140. package/build/users-permissions-translation-ko-json.90c2d129.chunk.js +1 -0
  141. package/build/users-permissions-translation-ms-json.dc405667.chunk.js +1 -0
  142. package/build/users-permissions-translation-nl-json.2d8e847a.chunk.js +1 -0
  143. package/build/users-permissions-translation-pl-json.b150dfb0.chunk.js +1 -0
  144. package/build/users-permissions-translation-pt-BR-json.0c494c69.chunk.js +1 -0
  145. package/build/users-permissions-translation-pt-json.0fccc389.chunk.js +1 -0
  146. package/build/users-permissions-translation-ru-json.4389c542.chunk.js +1 -0
  147. package/build/users-permissions-translation-sk-json.2602e768.chunk.js +1 -0
  148. package/build/users-permissions-translation-sv-json.438e46f7.chunk.js +1 -0
  149. package/build/users-permissions-translation-th-json.abe0558b.chunk.js +1 -0
  150. package/build/users-permissions-translation-tr-json.269ee593.chunk.js +1 -0
  151. package/build/users-permissions-translation-uk-json.ffd9a4ee.chunk.js +1 -0
  152. package/build/users-permissions-translation-vi-json.c2cd19d5.chunk.js +1 -0
  153. package/build/users-permissions-translation-zh-Hans-json.2d909528.chunk.js +1 -0
  154. package/build/users-permissions-translation-zh-json.7f3027c5.chunk.js +1 -0
  155. package/build/vi-json.12dacb71.chunk.js +1 -0
  156. package/build/webhook-list-page.949cefb9.chunk.js +1 -0
  157. package/build/zh-Hans-json.85999634.chunk.js +1 -0
  158. package/build/zh-json.2e957d0f.chunk.js +1 -0
  159. package/package.json +7 -7
  160. package/admin/src/components/AutoReloadOverlayBlockerProvider/Content.js +0 -29
  161. package/admin/src/components/AutoReloadOverlayBlockerProvider/Wrapper.js +0 -94
@@ -1,16 +1,37 @@
1
1
  import React, { useEffect } from 'react';
2
2
  import ReactDOM from 'react-dom';
3
- import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3
+ import { useIntl } from 'react-intl';
4
+ import styled, { keyframes } from 'styled-components';
5
+ import Time from '@strapi/icons/Time';
6
+ import Reload from '@strapi/icons/Reload';
7
+ import { Link } from '@strapi/parts/Link';
8
+ import { Box } from '@strapi/parts/Box';
9
+ import { Stack } from '@strapi/parts/Stack';
10
+ import { Row } from '@strapi/parts/Row';
11
+ import { H1, H2 } from '@strapi/parts/Text';
4
12
  import PropTypes from 'prop-types';
5
- import Content from './Content';
6
13
  import Overlay from './Overlay';
7
- import Wrapper from './Wrapper';
8
14
 
9
15
  const overlayContainer = document.createElement('div');
10
16
  const ID = 'autoReloadOverlayBlocker';
11
17
  overlayContainer.setAttribute('id', ID);
12
18
 
13
- const Blocker = ({ className, displayedIcon, description, title, elapsed, isOpen }) => {
19
+ const rotation = keyframes`
20
+ from {
21
+ transform: rotate(0deg);
22
+ }
23
+ to {
24
+ transform: rotate(359deg);
25
+ }
26
+ `;
27
+
28
+ const LoaderReload = styled(Reload)`
29
+ animation: ${rotation} 1s infinite linear;
30
+ ${({ small }) => small && `width: 25px; height: 25px;`}
31
+ `;
32
+
33
+ const Blocker = ({ displayedIcon, description, title, elapsed, isOpen }) => {
34
+ const { formatMessage } = useIntl();
14
35
  useEffect(() => {
15
36
  document.body.appendChild(overlayContainer);
16
37
 
@@ -22,26 +43,38 @@ const Blocker = ({ className, displayedIcon, description, title, elapsed, isOpen
22
43
  if (isOpen) {
23
44
  return ReactDOM.createPortal(
24
45
  <Overlay>
25
- <Wrapper>
26
- <div className={className}>
27
- <FontAwesomeIcon icon={displayedIcon} />
28
- </div>
29
- <div>
30
- <Content description={description} title={title} />
31
- {elapsed < 15 && (
32
- <div className="buttonContainer">
33
- <a
34
- className="primary btn"
35
- href="https://strapi.io/documentation"
36
- target="_blank"
37
- rel="noopener noreferrer"
38
- >
39
- Read the documentation
40
- </a>
41
- </div>
46
+ <Box>
47
+ <Row>
48
+ {displayedIcon === 'reload' && (
49
+ <Box paddingRight={3} style={{ alignSelf: 'baseline' }}>
50
+ <LoaderReload width="4rem" height="4rem" />
51
+ </Box>
52
+ )}
53
+ {displayedIcon === 'time' && (
54
+ <Box paddingRight={3} style={{ alignSelf: 'center' }}>
55
+ <Time width="3.8rem" height="3.8rem" />
56
+ </Box>
42
57
  )}
43
- </div>
44
- </Wrapper>
58
+ <Stack size={2}>
59
+ <H1>{formatMessage(title)}</H1>
60
+ <H2 textColor="neutral600">{formatMessage(description)}</H2>
61
+ <Row>
62
+ {elapsed < 15 && (
63
+ <Link
64
+ href="https://strapi.io/documentation"
65
+ target="_blank"
66
+ onClick={e => {
67
+ e.preventDefault();
68
+ window.open('https://strapi.io/documentation', '_blank');
69
+ }}
70
+ >
71
+ Read the documentation
72
+ </Link>
73
+ )}
74
+ </Row>
75
+ </Stack>
76
+ </Row>
77
+ </Box>
45
78
  </Overlay>,
46
79
  overlayContainer
47
80
  );
@@ -51,7 +84,6 @@ const Blocker = ({ className, displayedIcon, description, title, elapsed, isOpen
51
84
  };
52
85
 
53
86
  Blocker.propTypes = {
54
- className: PropTypes.string.isRequired,
55
87
  displayedIcon: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired,
56
88
  description: PropTypes.object.isRequired,
57
89
  elapsed: PropTypes.number.isRequired,
@@ -11,24 +11,12 @@ const Overlay = styled.div`
11
11
  &:before {
12
12
  content: '';
13
13
  position: fixed;
14
- top: 6rem;
14
+ top: 0;
15
15
  right: 0;
16
16
  bottom: 0;
17
17
  left: 0;
18
- background: linear-gradient(rgba(0, 0, 0, 15) 0%, rgba(0, 0, 0, 0) 100%);
19
- opacity: 0.5;
20
- }
21
-
22
- &:after {
23
- content: '';
24
- position: fixed;
25
- top: 6rem;
26
- right: 0;
27
- bottom: 0;
28
- left: 24rem;
29
- background: linear-gradient(#fbfbfb 20%, rgba(0, 0, 100, 0) 100%);
30
- box-shadow: inset 0px 2px 4px rgba(0, 0, 0, 0.1);
31
- box-shadow: inset 0 1px 2px 0 rgba(40, 42, 49, 0.16);
18
+ background: ${({ theme }) => theme.colors.neutral200};
19
+ opacity: 0.8;
32
20
  }
33
21
 
34
22
  > div {
@@ -28,7 +28,8 @@ const AutoReloadOverlayBlockerProvider = ({ children }) => {
28
28
 
29
29
  if (isOpen) {
30
30
  timer = setInterval(() => {
31
- if (elapsed > 15) {
31
+ // if (elapsed > 15) {
32
+ if (elapsed > 30) {
32
33
  clearInterval(timer);
33
34
 
34
35
  return null;
@@ -47,8 +48,8 @@ const AutoReloadOverlayBlockerProvider = ({ children }) => {
47
48
  };
48
49
  }, [isOpen, elapsed]);
49
50
 
50
- let displayedIcon = config?.icon || 'sync-alt';
51
- let className = 'icoContainer spinner';
51
+ let displayedIcon = config?.icon || 'reload';
52
+
52
53
  let description = {
53
54
  id: config?.description || 'components.OverlayBlocker.description',
54
55
  defaultMessage:
@@ -60,8 +61,8 @@ const AutoReloadOverlayBlockerProvider = ({ children }) => {
60
61
  };
61
62
 
62
63
  if (elapsed > 15) {
63
- displayedIcon = ['far', 'clock'];
64
- className = 'icoContainer';
64
+ displayedIcon = 'time';
65
+
65
66
  description = {
66
67
  id: 'components.OverlayBlocker.description.serverError',
67
68
  defaultMessage: 'The server should have restarted, please check your logs in the terminal.',
@@ -81,7 +82,6 @@ const AutoReloadOverlayBlockerProvider = ({ children }) => {
81
82
  displayedIcon={displayedIcon}
82
83
  isOpen={isOpen}
83
84
  elapsed={elapsed}
84
- className={className}
85
85
  description={description}
86
86
  title={title}
87
87
  />
@@ -1,10 +1,9 @@
1
- import React from 'react';
1
+ import React, { useRef, useState } from 'react';
2
+ import styled from 'styled-components';
2
3
  import PropTypes from 'prop-types';
3
4
  import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
4
5
  import { useIntl } from 'react-intl';
5
- import { useHistory } from 'react-router-dom';
6
- import styled from 'styled-components';
7
- import { Button } from '@strapi/parts/Button';
6
+ import { NavLink as Link } from 'react-router-dom';
8
7
  import { Divider } from '@strapi/parts/Divider';
9
8
  import {
10
9
  MainNav,
@@ -15,7 +14,12 @@ import {
15
14
  NavUser,
16
15
  NavCondense,
17
16
  } from '@strapi/parts/MainNav';
17
+ import { FocusTrap } from '@strapi/parts/FocusTrap';
18
+ import { Box } from '@strapi/parts/Box';
19
+ import { Text } from '@strapi/parts/Text';
20
+ import { Stack } from '@strapi/parts/Stack';
18
21
  import ContentIcon from '@strapi/icons/ContentIcon';
22
+ import Logout from '@strapi/icons/Logout';
19
23
  import { auth, usePersistentState, useAppInfos } from '@strapi/helper-plugin';
20
24
  import useConfigurations from '../../hooks/useConfigurations';
21
25
 
@@ -26,13 +30,64 @@ const IconWrapper = styled.span`
26
30
  }
27
31
  `;
28
32
 
33
+ const LinkUserWrapper = styled(Box)`
34
+ width: ${150 / 16}rem;
35
+ position: absolute;
36
+ bottom: ${({ theme }) => theme.spaces[9]};
37
+ left: ${({ theme }) => theme.spaces[5]};
38
+ `;
39
+
40
+ const LinkUser = styled(Link)`
41
+ display: flex;
42
+ justify-content: space-between;
43
+ align-items: center;
44
+ text-decoration: none;
45
+ padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[4]}`};
46
+ border-radius: ${({ theme }) => theme.spaces[1]};
47
+
48
+ &:hover {
49
+ background: ${({ theme, logout }) =>
50
+ logout ? theme.colors.danger100 : theme.colors.primary100};
51
+ text-decoration: none;
52
+ }
53
+
54
+ svg {
55
+ path {
56
+ fill: ${({ theme }) => theme.colors.danger600};
57
+ }
58
+ }
59
+ `;
60
+
29
61
  const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
62
+ const buttonRef = useRef();
63
+ const [userLinksVisible, setUserLinksVisible] = useState(false);
30
64
  const { menuLogo } = useConfigurations();
31
- const { push } = useHistory();
32
65
  const [condensed, setCondensed] = usePersistentState('navbar-condensed', false);
33
66
  const { userDisplayName } = useAppInfos();
34
67
  const { formatMessage } = useIntl();
35
68
 
69
+ const initials = userDisplayName
70
+ .split(' ')
71
+ .map(name => name.substring(0, 1))
72
+ .join('')
73
+ .substring(0, 2);
74
+
75
+ const handleToggleUserLinks = () => setUserLinksVisible(prev => !prev);
76
+
77
+ const handleLogout = () => {
78
+ auth.clearAppStorage();
79
+ handleToggleUserLinks();
80
+ };
81
+
82
+ const handleBlur = e => {
83
+ if (
84
+ !e.currentTarget.contains(e.relatedTarget) &&
85
+ e.relatedTarget?.parentElement?.id !== 'main-nav-user-button'
86
+ ) {
87
+ setUserLinksVisible(false);
88
+ }
89
+ };
90
+
36
91
  return (
37
92
  <MainNav condensed={condensed}>
38
93
  <NavBrand
@@ -80,23 +135,43 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
80
135
  {formatMessage(link.intlLabel)}
81
136
  </NavLink>
82
137
  ))}
83
- {/* This is temporary */}
84
- <Button
85
- type="button"
86
- onClick={() => {
87
- auth.clearAppStorage();
88
- push('/auth/login');
89
- }}
90
- >
91
- Logout
92
- </Button>
93
138
  </NavSection>
94
139
  ) : null}
95
140
  </NavSections>
96
141
 
97
- <NavUser src="https://avatars.githubusercontent.com/u/3874873?v=4" to="/me">
142
+ <NavUser
143
+ id="main-nav-user-button"
144
+ ref={buttonRef}
145
+ onClick={handleToggleUserLinks}
146
+ initials={initials}
147
+ >
98
148
  {userDisplayName}
99
149
  </NavUser>
150
+ {userLinksVisible && (
151
+ <LinkUserWrapper onBlur={handleBlur} padding={1} shadow="tableShadow" background="neutral0">
152
+ <FocusTrap onEscape={handleToggleUserLinks}>
153
+ <Stack size={0}>
154
+ <LinkUser onClick={handleToggleUserLinks} to="/me">
155
+ <Text>
156
+ {formatMessage({
157
+ id: 'app.components.LeftMenu.profile',
158
+ defaultMessage: 'Profile',
159
+ })}
160
+ </Text>
161
+ </LinkUser>
162
+ <LinkUser onClick={handleLogout} logout="logout" to="/auth/login">
163
+ <Text textColor="danger600">
164
+ {formatMessage({
165
+ id: 'app.components.LeftMenu.logout',
166
+ defaultMessage: 'Logout',
167
+ })}
168
+ </Text>
169
+ <Logout />
170
+ </LinkUser>
171
+ </Stack>
172
+ </FocusTrap>
173
+ </LinkUserWrapper>
174
+ )}
100
175
 
101
176
  <NavCondense onClick={() => setCondensed(s => !s)}>
102
177
  {condensed
@@ -1,4 +1,4 @@
1
- import React, { useState } from 'react';
1
+ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import styled from 'styled-components';
4
4
  import { Row } from '@strapi/parts/Row';
@@ -12,7 +12,6 @@ const Wrapper = styled(Row)`
12
12
  border: 1px solid ${({ theme }) => theme.colors.neutral200};
13
13
  background: ${({ theme }) => theme.colors.neutral150};
14
14
  padding-left: 1px;
15
- z-index: ${({ hovering }) => (hovering ? 1 : undefined)};
16
15
 
17
16
  span {
18
17
  line-height: 0.6rem;
@@ -20,29 +19,16 @@ const Wrapper = styled(Row)`
20
19
  }
21
20
  `;
22
21
 
23
- const FileWrapper = ({ children, preview }) => {
24
- const [previewVisible, setPreviewVisible] = useState(false);
25
-
22
+ const FileWrapper = ({ children, ...props }) => {
26
23
  return (
27
- <Wrapper
28
- justifyContent="center"
29
- alignItems="center"
30
- hovering={preview && previewVisible}
31
- onMouseEnter={() => setPreviewVisible(true)}
32
- onMouseLeave={() => setPreviewVisible(false)}
33
- >
24
+ <Wrapper justifyContent="center" alignItems="center" as="span" {...props}>
34
25
  <TableLabel textColor="neutral600">{children}</TableLabel>
35
26
  </Wrapper>
36
27
  );
37
28
  };
38
29
 
39
- FileWrapper.defaultProps = {
40
- preview: true,
41
- };
42
-
43
30
  FileWrapper.propTypes = {
44
31
  children: PropTypes.string.isRequired,
45
- preview: PropTypes.bool,
46
32
  };
47
33
 
48
34
  export default FileWrapper;
@@ -280,4 +280,7 @@ Inputs.propTypes = {
280
280
 
281
281
  const Memoized = memo(Inputs, isEqual);
282
282
 
283
- export default connect(Memoized, select);
283
+ export default connect(
284
+ Memoized,
285
+ select
286
+ );
@@ -437,4 +437,7 @@ SelectWrapper.propTypes = {
437
437
 
438
438
  const Memoized = memo(SelectWrapper);
439
439
 
440
- export default connect(Memoized, select);
440
+ export default connect(
441
+ Memoized,
442
+ select
443
+ );
@@ -46,7 +46,7 @@ const DeleteLink = ({ isCreatingEntry, onDelete, onDeleteSucceeded, trackerPrope
46
46
 
47
47
  return (
48
48
  <>
49
- <Button onClick={toggleWarningDelete} size="S" startIcon={<Delete />} variant="danger">
49
+ <Button onClick={toggleWarningDelete} size="S" startIcon={<Delete />} variant="danger-light">
50
50
  {formatMessage({
51
51
  id: getTrad('containers.Edit.delete-entry'),
52
52
  defaultMessage: 'Delete this entry',
@@ -71,4 +71,7 @@ DeleteLink.propTypes = {
71
71
 
72
72
  const Memoized = memo(DeleteLink, isEqual);
73
73
 
74
- export default connect(Memoized, select);
74
+ export default connect(
75
+ Memoized,
76
+ select
77
+ );
@@ -40,8 +40,8 @@ const ForgotPassword = ({ onSubmit, schema }) => {
40
40
  <Box paddingTop={6} paddingBottom={7}>
41
41
  <H1>
42
42
  {formatMessage({
43
- id: 'Auth.form.button.password-forgotten',
44
- defaultMessage: 'Password forgotten',
43
+ id: 'Auth.form.button.password-recovery',
44
+ defaultMessage: 'Password Recovery',
45
45
  })}
46
46
  </H1>
47
47
  </Box>
@@ -44,7 +44,7 @@ const Login = ({ onSubmit, schema, children }) => {
44
44
  <H1>
45
45
  {formatMessage({
46
46
  id: 'Auth.form.welcome.title',
47
- defaultMessage: 'Welcome back!',
47
+ defaultMessage: 'Welcome!',
48
48
  })}
49
49
  </H1>
50
50
  </Box>
@@ -110,7 +110,7 @@ const Register = ({ fieldsToDisable, noSignin, onSubmit, schema }) => {
110
110
  <H1>
111
111
  {formatMessage({
112
112
  id: 'Auth.form.welcome.title',
113
- defaultMessage: 'Welcome back!',
113
+ defaultMessage: 'Welcome!',
114
114
  })}
115
115
  </H1>
116
116
  </Box>
@@ -53,7 +53,11 @@ const ContentBlocks = () => {
53
53
  iconBackground="warning100"
54
54
  />
55
55
  </BlockLink>
56
- <BlockLink href="https://strapi.io/blog" target="_blank" rel="noopener noreferrer nofollow">
56
+ <BlockLink
57
+ href="https://strapi.io/blog/categories/tutorials"
58
+ target="_blank"
59
+ rel="noopener noreferrer nofollow"
60
+ >
57
61
  <ContentBox
58
62
  title={formatMessage({
59
63
  id: 'app.components.BlockLink.tutorial',
@@ -16,10 +16,57 @@ import ExternalLink from '@strapi/icons/ExternalLink';
16
16
  import Github from '@strapi/icons/Github';
17
17
  import Slack from '@strapi/icons/Slack';
18
18
  import Reddit from '@strapi/icons/Reddit';
19
+ import Strapi from '@strapi/icons/Strapi';
19
20
  import Twitter from '@strapi/icons/Twitter';
20
- import Medium from '@strapi/icons/Medium';
21
21
  import Discourse from '@strapi/icons/Discourse';
22
22
 
23
+ const StyledReddit = styled(Reddit)`
24
+ > path:first-child {
25
+ fill: #ff4500;
26
+ }
27
+ > path:last-child {
28
+ fill: ${({ theme }) => theme.colors.neutral0};
29
+ }
30
+ `;
31
+ const StyledStrapi = styled(Strapi)`
32
+ > path:first-child {
33
+ fill: #8e75ff;
34
+ }
35
+ > path:nth-child(2) {
36
+ fill: #8e75ff;
37
+ }
38
+ > path:nth-child(3) {
39
+ fill: #8e75ff;
40
+ }
41
+ `;
42
+
43
+ const StyledTwitter = styled(Twitter)`
44
+ path {
45
+ fill: #1da1f2 !important;
46
+ }
47
+ `;
48
+
49
+ const StyledDiscourse = styled(Discourse)`
50
+ > path:first-child {
51
+ fill: #231f20;
52
+ }
53
+ > path:nth-child(2) {
54
+ fill: #fff9ae;
55
+ }
56
+ > path:nth-child(3) {
57
+ fill: #00aeef;
58
+ }
59
+ > path:nth-child(4) {
60
+ fill: #00a94f;
61
+ }
62
+ > path:nth-child(5) {
63
+ fill: #f15d22;
64
+ }
65
+ > path:nth-child(6) {
66
+ fill: #e31b23;
67
+ }
68
+ `;
69
+
23
70
  const socialLinks = [
24
71
  {
25
72
  name: 'Github',
@@ -36,27 +83,33 @@ const socialLinks = [
36
83
  {
37
84
  name: 'Reddit',
38
85
  link: 'https://www.reddit.com/r/Strapi/',
39
- icon: <Reddit />,
86
+ icon: <StyledReddit />,
40
87
  alt: 'reddit',
41
88
  },
42
89
  {
43
90
  name: 'Twitter',
44
91
  link: 'https://twitter.com/strapijs',
45
- icon: <Twitter />,
92
+ icon: <StyledTwitter />,
46
93
  alt: 'twitter',
47
94
  },
48
95
  {
49
96
  name: 'Medium',
50
97
  link: 'https://medium.com/@strapi',
51
- icon: <Medium />,
98
+ icon: <StyledStrapi />,
52
99
  alt: 'medium',
53
100
  },
54
101
  {
55
102
  name: 'Forum',
56
103
  link: 'https://forum.strapi.io',
57
- icon: <Discourse />,
104
+ icon: <StyledDiscourse />,
58
105
  alt: 'forum',
59
106
  },
107
+ {
108
+ name: 'Career',
109
+ link: 'https://strapi.io/careers',
110
+ icon: <StyledStrapi />,
111
+ alt: 'career',
112
+ },
60
113
  ];
61
114
 
62
115
  const LinkCustom = styled(LinkButton)`
@@ -115,7 +168,10 @@ const SocialLinks = () => {
115
168
  })}
116
169
  </WordWrap>
117
170
  </Stack>
118
- <Link href="https://strapi.io/" endIcon={<ExternalLink />}>
171
+ <Link
172
+ href="https://portal.productboard.com/strapi/1-roadmap/tabs/2-under-consideration"
173
+ endIcon={<ExternalLink />}
174
+ >
119
175
  {formatMessage({
120
176
  id: 'app.components.HomePage.roadmap',
121
177
  defaultMessage: 'See our road map',
@@ -73,9 +73,9 @@ const ConditionsModal = ({ actions, headerBreadCrumbs, isFormDisabled, onClosed,
73
73
  };
74
74
 
75
75
  return (
76
- <ModalLayout onClose={onClosed}>
76
+ <ModalLayout labelledBy="condition-modal-breadcrumbs" onClose={onClosed}>
77
77
  <ModalHeader>
78
- <Breadcrumbs label={headerBreadCrumbs.join(', ')}>
78
+ <Breadcrumbs id="condition-modal-breadcrumbs" label={headerBreadCrumbs.join(', ')}>
79
79
  {headerBreadCrumbs.map(label => (
80
80
  <Crumb key={label}>
81
81
  {upperFirst(
@@ -18,6 +18,7 @@ import { cellWidth, rowHeight } from '../../Permissions/utils/constants';
18
18
  import RowLabelWithCheckbox from '../../RowLabelWithCheckbox';
19
19
  import { getCheckboxState } from '../../utils';
20
20
  import generateCheckboxesActions from './utils/generateCheckboxesActions';
21
+ import activeStyle from '../utils/activeStyle';
21
22
 
22
23
  const activeRowStyle = (theme, isActive) => `
23
24
  ${Wrapper} {
@@ -31,6 +32,10 @@ const activeRowStyle = (theme, isActive) => `
31
32
  ${ConditionsButton} {
32
33
  display: block;
33
34
  }
35
+ &:hover {
36
+ ${activeStyle(theme)}
37
+ }
38
+
34
39
  `;
35
40
 
36
41
  const Wrapper = styled.div`
@@ -75,7 +80,7 @@ const Chevron = styled(Box)`
75
80
  }
76
81
  `;
77
82
 
78
- const TinyDot = styled(Box)`
83
+ const TinyDot = styled.span`
79
84
  position: absolute;
80
85
  top: -6px;
81
86
  left: 37px;
@@ -228,7 +233,6 @@ const Collapse = ({
228
233
  }
229
234
  )}
230
235
  </Row>
231
- <Box style={{ width: 120 }} />
232
236
  {isModalOpen && (
233
237
  <ConditionsModal
234
238
  headerBreadCrumbs={[label, 'app.components.LeftMenuLinkContainer.settings']}
@@ -2,6 +2,7 @@ import React, { memo } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Box } from '@strapi/parts/Box';
4
4
  import styled from 'styled-components';
5
+ import sortBy from 'lodash/sortBy';
5
6
  import ContentTypeCollapses from '../ContentTypeCollapses';
6
7
  import GlobalActions from '../GlobalActions';
7
8
 
@@ -10,7 +11,7 @@ const StyledBox = styled(Box)`
10
11
  `;
11
12
 
12
13
  const ContentTypes = ({ isFormDisabled, kind, layout: { actions, subjects } }) => {
13
- const sortedSubjects = [...subjects].sort((a, b) => a.label > b.label);
14
+ const sortedSubjects = sortBy([...subjects], 'label');
14
15
 
15
16
  return (
16
17
  <StyledBox background="neutral0">
@@ -6,19 +6,9 @@ import { Stack } from '@strapi/parts/Stack';
6
6
  import { Text } from '@strapi/parts/Text';
7
7
  import { Textarea } from '@strapi/parts/Textarea';
8
8
  import { TextInput } from '@strapi/parts/TextInput';
9
+ import { Button } from '@strapi/parts/Button';
9
10
  import PropTypes from 'prop-types';
10
11
  import { useIntl } from 'react-intl';
11
- import styled from 'styled-components';
12
-
13
- const UsersRoleNumber = styled.div`
14
- border: 1px solid ${({ theme }) => theme.colors.primary200};
15
- background: ${({ theme }) => theme.colors.primary100};
16
- padding: ${({ theme }) => `${theme.spaces[2]} ${theme.spaces[4]}`};
17
- color: ${({ theme }) => theme.colors.primary600};
18
- border-radius: ${({ theme }) => theme.borderRadius};
19
- font-size: ${12 / 16}rem;
20
- font-weight: bold;
21
- `;
22
12
 
23
13
  const RoleForm = ({ disabled, role, values, errors, onChange, onBlur }) => {
24
14
  const { formatMessage } = useIntl();
@@ -50,7 +40,7 @@ const RoleForm = ({ disabled, role, values, errors, onChange, onBlur }) => {
50
40
  </Text>
51
41
  </Box>
52
42
  </Box>
53
- <UsersRoleNumber>
43
+ <Button disabled variant="secondary">
54
44
  {formatMessage(
55
45
  {
56
46
  id: 'Settings.roles.form.button.users-with-role',
@@ -59,7 +49,7 @@ const RoleForm = ({ disabled, role, values, errors, onChange, onBlur }) => {
59
49
  },
60
50
  { number: role.usersCount }
61
51
  )}
62
- </UsersRoleNumber>
52
+ </Button>
63
53
  </Row>
64
54
  <Grid gap={4}>
65
55
  <GridItem col={6}>
@@ -310,8 +310,8 @@ const ListView = () => {
310
310
  icon={<AddIcon />}
311
311
  >
312
312
  {formatMessage({
313
- id: 'Settings.webhooks.list.field.add',
314
- defaultMessage: 'Add another field to this collection type',
313
+ id: 'Settings.webhooks.list.button.add',
314
+ defaultMessage: 'Add new webhook',
315
315
  })}
316
316
  </TFooter>
317
317
  }