@strapi/admin 4.6.1 → 4.9.0-alpha.0

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 (196) hide show
  1. package/admin/src/assets/images/onboarding-preview.png +0 -0
  2. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +4 -14
  3. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +1 -1
  4. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +2 -0
  5. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +39 -9
  6. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +9 -15
  7. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +4 -12
  8. package/admin/src/content-manager/pages/EditView/DeleteLink/index.js +6 -8
  9. package/admin/src/content-manager/pages/ListView/index.js +6 -11
  10. package/admin/src/index.js +1 -0
  11. package/admin/src/pages/Admin/Onboarding/constants.js +46 -0
  12. package/admin/src/pages/Admin/Onboarding/index.js +161 -89
  13. package/admin/src/pages/Admin/index.js +5 -2
  14. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +15 -2
  15. package/admin/src/pages/SettingsPage/pages/Users/components/MagicLink/MagicLinkWrapper.js +3 -20
  16. package/admin/src/permissions/defaultPermissions.js +2 -15
  17. package/admin/src/translations/ar.json +4 -4
  18. package/admin/src/translations/ca.json +4 -4
  19. package/admin/src/translations/cs.json +4 -4
  20. package/admin/src/translations/de.json +4 -4
  21. package/admin/src/translations/dk.json +4 -4
  22. package/admin/src/translations/en.json +14 -5
  23. package/admin/src/translations/es.json +4 -4
  24. package/admin/src/translations/eu.json +4 -4
  25. package/admin/src/translations/fr.json +4 -4
  26. package/admin/src/translations/gu.json +4 -4
  27. package/admin/src/translations/he.json +4 -4
  28. package/admin/src/translations/hi.json +4 -4
  29. package/admin/src/translations/hu.json +4 -4
  30. package/admin/src/translations/id.json +4 -4
  31. package/admin/src/translations/it.json +4 -4
  32. package/admin/src/translations/ja.json +4 -4
  33. package/admin/src/translations/ko.json +4 -4
  34. package/admin/src/translations/ml.json +4 -4
  35. package/admin/src/translations/ms.json +4 -4
  36. package/admin/src/translations/nl.json +4 -4
  37. package/admin/src/translations/no.json +4 -4
  38. package/admin/src/translations/pl.json +4 -4
  39. package/admin/src/translations/pt-BR.json +4 -4
  40. package/admin/src/translations/pt.json +4 -4
  41. package/admin/src/translations/ru.json +785 -789
  42. package/admin/src/translations/sa.json +4 -4
  43. package/admin/src/translations/sk.json +4 -4
  44. package/admin/src/translations/sv.json +4 -4
  45. package/admin/src/translations/th.json +4 -4
  46. package/admin/src/translations/tr.json +4 -4
  47. package/admin/src/translations/uk.json +4 -4
  48. package/admin/src/translations/vi.json +4 -4
  49. package/admin/src/translations/zh-Hans.json +4 -4
  50. package/admin/src/translations/zh.json +4 -4
  51. package/build/1683.d59d0f23.chunk.js +268 -0
  52. package/build/19eb2dfcf2603eb55733.png +0 -0
  53. package/build/{4855.bd092921.chunk.js → 2223.1bfea951.chunk.js} +88 -88
  54. package/build/2743.646a1015.chunk.js +45 -0
  55. package/build/3075.3ee481f1.chunk.js +108 -0
  56. package/build/3632.2e378cf8.chunk.js +138 -0
  57. package/build/{4318.f96a9d4d.chunk.js → 4318.cd55ce02.chunk.js} +1 -1
  58. package/build/9707.b36ed71e.chunk.js +96 -0
  59. package/build/Admin-authenticatedApp.a73577e1.chunk.js +79 -0
  60. package/build/{Admin_InternalErrorPage.157152a8.chunk.js → Admin_InternalErrorPage.178ddb90.chunk.js} +1 -1
  61. package/build/{Admin_homePage.b1730882.chunk.js → Admin_homePage.c2f5f27d.chunk.js} +2 -2
  62. package/build/{Admin_marketplace.ea0316c2.chunk.js → Admin_marketplace.1df49c42.chunk.js} +1 -1
  63. package/build/{Admin_pluginsPage.5c24f963.chunk.js → Admin_pluginsPage.8d824408.chunk.js} +2 -2
  64. package/build/{Admin_profilePage.59af1978.chunk.js → Admin_profilePage.cb667bc5.chunk.js} +2 -2
  65. package/build/Admin_settingsPage.f90615fb.chunk.js +178 -0
  66. package/build/{Upload_ConfigureTheView.3f2b6e6a.chunk.js → Upload_ConfigureTheView.d306009d.chunk.js} +1 -1
  67. package/build/admin-app.06f07029.chunk.js +112 -0
  68. package/build/admin-edit-roles-page.35199b9d.chunk.js +1 -0
  69. package/build/admin-edit-users.9e48b00d.chunk.js +10 -0
  70. package/build/admin-users.cf7b4151.chunk.js +11 -0
  71. package/build/{api-tokens-create-page.d248362d.chunk.js → api-tokens-create-page.a31c7fba.chunk.js} +1 -1
  72. package/build/{api-tokens-edit-page.8516fa20.chunk.js → api-tokens-edit-page.64fef287.chunk.js} +1 -1
  73. package/build/{api-tokens-list-page.44a79fda.chunk.js → api-tokens-list-page.e600ad3e.chunk.js} +2 -2
  74. package/build/ar-json.39e54aba.chunk.js +1 -0
  75. package/build/{audit-logs-settings-page.c3dce30d.chunk.js → audit-logs-settings-page.d4da4579.chunk.js} +1 -1
  76. package/build/{ca-json.f6a0f472.chunk.js → ca-json.4d999055.chunk.js} +1 -1
  77. package/build/content-manager.255c3a59.chunk.js +1139 -0
  78. package/build/{content-type-builder-list-view.79e84b36.chunk.js → content-type-builder-list-view.8d7a3d68.chunk.js} +5 -5
  79. package/build/content-type-builder.3c8558a5.chunk.js +126 -0
  80. package/build/cs-json.4b44411c.chunk.js +1 -0
  81. package/build/{de-json.30e1f35b.chunk.js → de-json.866f8a28.chunk.js} +1 -1
  82. package/build/{dk-json.e6d9ffa4.chunk.js → dk-json.10f7b1d1.chunk.js} +1 -1
  83. package/build/email-settings-page.b19f2eb2.chunk.js +10 -0
  84. package/build/en-json.1997583c.chunk.js +1 -0
  85. package/build/es-json.ea15c957.chunk.js +1 -0
  86. package/build/{eu-json.fceecd8b.chunk.js → eu-json.3bc24d60.chunk.js} +1 -1
  87. package/build/{fr-json.78545ef8.chunk.js → fr-json.e88fbdfd.chunk.js} +1 -1
  88. package/build/{gu-json.676518f2.chunk.js → gu-json.94f0d242.chunk.js} +1 -1
  89. package/build/{he-json.ad22e8cc.chunk.js → he-json.f0de8cdb.chunk.js} +1 -1
  90. package/build/{hi-json.19b51c09.chunk.js → hi-json.df3a7be2.chunk.js} +1 -1
  91. package/build/{hu-json.f947088f.chunk.js → hu-json.680e6eef.chunk.js} +1 -1
  92. package/build/{i18n-settings-page.b8d8753e.chunk.js → i18n-settings-page.a6b49eac.chunk.js} +1 -1
  93. package/build/{id-json.504daa84.chunk.js → id-json.e0d83d41.chunk.js} +1 -1
  94. package/build/index.html +1 -1
  95. package/build/{it-json.2fd90f4d.chunk.js → it-json.8be59205.chunk.js} +1 -1
  96. package/build/{ja-json.c9f12d0b.chunk.js → ja-json.97ee41ba.chunk.js} +1 -1
  97. package/build/{ko-json.ef463065.chunk.js → ko-json.4cbbf4f2.chunk.js} +1 -1
  98. package/build/main.7f308c20.js +4322 -0
  99. package/build/{ml-json.490f666c.chunk.js → ml-json.e3747091.chunk.js} +1 -1
  100. package/build/ms-json.0eddffd9.chunk.js +1 -0
  101. package/build/{nl-json.c416295a.chunk.js → nl-json.371a15ee.chunk.js} +1 -1
  102. package/build/{no-json.1a2258ba.chunk.js → no-json.9b3cd181.chunk.js} +1 -1
  103. package/build/{pl-json.8cf0c871.chunk.js → pl-json.e535cbce.chunk.js} +1 -1
  104. package/build/{pt-BR-json.51fab8d0.chunk.js → pt-BR-json.e5fafa46.chunk.js} +1 -1
  105. package/build/pt-json.ee554a41.chunk.js +1 -0
  106. package/build/review-workflows-settings.7b4be1b0.chunk.js +63 -0
  107. package/build/{ru-json.aa5cd123.chunk.js → ru-json.866f0ff1.chunk.js} +1 -1
  108. package/build/runtime~main.bf374148.js +2 -0
  109. package/build/{sa-json.f3fa5407.chunk.js → sa-json.7efeb257.chunk.js} +1 -1
  110. package/build/{sk-json.9ec60d9f.chunk.js → sk-json.7bbeb0af.chunk.js} +1 -1
  111. package/build/{sso-settings-page.b85ad080.chunk.js → sso-settings-page.ad2143dd.chunk.js} +1 -1
  112. package/build/{sv-json.c6b0c237.chunk.js → sv-json.dc40951f.chunk.js} +1 -1
  113. package/build/{th-json.6e68155c.chunk.js → th-json.f664b96d.chunk.js} +1 -1
  114. package/build/{tr-json.9f41dc08.chunk.js → tr-json.b79eae31.chunk.js} +1 -1
  115. package/build/uk-json.b7e38370.chunk.js +1 -0
  116. package/build/upload-settings.eb1a7908.chunk.js +84 -0
  117. package/build/upload.700e2c84.chunk.js +33 -0
  118. package/build/{users-advanced-settings-page.fce9908e.chunk.js → users-advanced-settings-page.aae212f2.chunk.js} +1 -1
  119. package/build/{users-email-settings-page.343d0ad2.chunk.js → users-email-settings-page.8a9b0da1.chunk.js} +1 -1
  120. package/build/{users-providers-settings-page.e5a9a3f1.chunk.js → users-providers-settings-page.e6be909d.chunk.js} +10 -10
  121. package/build/{users-roles-settings-page.66312f31.chunk.js → users-roles-settings-page.97d06a80.chunk.js} +3 -3
  122. package/build/vi-json.ee4c5537.chunk.js +1 -0
  123. package/build/webhook-edit-page.9eb0f789.chunk.js +75 -0
  124. package/build/webhook-list-page.66082323.chunk.js +42 -0
  125. package/build/{zh-Hans-json.9c0eac99.chunk.js → zh-Hans-json.30a18940.chunk.js} +1 -1
  126. package/build/{zh-json.f88f563d.chunk.js → zh-json.49d84433.chunk.js} +1 -1
  127. package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +12 -12
  128. package/ee/admin/hooks/useSettingsMenu/utils/customGlobalLinks.js +21 -13
  129. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +137 -0
  130. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +42 -0
  131. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/AddStage.js +87 -0
  132. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/index.js +1 -0
  133. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +90 -0
  134. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/index.js +1 -0
  135. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +77 -0
  136. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/index.js +1 -0
  137. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +6 -0
  138. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +63 -0
  139. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/index.js +3 -0
  140. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +102 -0
  141. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +25 -0
  142. package/ee/admin/pages/SettingsPage/utils/customRoutes.js +16 -2
  143. package/ee/admin/permissions/customPermissions.js +7 -0
  144. package/ee/server/bootstrap.js +7 -1
  145. package/ee/server/config/admin-actions.js +10 -0
  146. package/ee/server/constants/default-stages.json +14 -0
  147. package/ee/server/constants/default-workflow.json +1 -0
  148. package/ee/server/constants/workflows.js +7 -0
  149. package/ee/server/content-types/index.js +9 -0
  150. package/ee/server/content-types/workflow/index.js +34 -0
  151. package/ee/server/content-types/workflow-stage/index.js +36 -0
  152. package/ee/server/controllers/index.js +2 -0
  153. package/ee/server/controllers/workflows/index.js +36 -0
  154. package/ee/server/controllers/workflows/stages/index.js +57 -0
  155. package/ee/server/index.js +1 -0
  156. package/ee/server/routes/index.js +87 -0
  157. package/ee/server/services/index.js +3 -0
  158. package/ee/server/services/review-workflows/review-workflows.js +54 -0
  159. package/ee/server/services/review-workflows/stages.js +133 -0
  160. package/ee/server/services/review-workflows/workflows.js +25 -0
  161. package/ee/server/utils/index.js +8 -0
  162. package/ee/server/utils/test.js +11 -0
  163. package/ee/server/validation/review-workflows.js +17 -0
  164. package/package.json +15 -15
  165. package/server/config/admin-actions.js +0 -16
  166. package/server/controllers/admin.js +0 -55
  167. package/server/routes/admin.js +0 -28
  168. package/webpack.config.js +0 -3
  169. package/build/1683.c8aa7b7c.chunk.js +0 -268
  170. package/build/2743.6d1632f9.chunk.js +0 -45
  171. package/build/3075.dc3894fe.chunk.js +0 -108
  172. package/build/3632.0317b618.chunk.js +0 -138
  173. package/build/9707.7290fd92.chunk.js +0 -96
  174. package/build/Admin-authenticatedApp.ce646f66.chunk.js +0 -75
  175. package/build/Admin_settingsPage.d1493824.chunk.js +0 -178
  176. package/build/admin-app.25934eaa.chunk.js +0 -112
  177. package/build/admin-edit-roles-page.446b69dc.chunk.js +0 -1
  178. package/build/admin-edit-users.2ed69bfd.chunk.js +0 -10
  179. package/build/admin-users.fc003b10.chunk.js +0 -11
  180. package/build/ar-json.932794f7.chunk.js +0 -1
  181. package/build/content-manager.35ff9726.chunk.js +0 -1139
  182. package/build/content-type-builder.855db321.chunk.js +0 -126
  183. package/build/cs-json.79879fb6.chunk.js +0 -1
  184. package/build/email-settings-page.d1fcc7a3.chunk.js +0 -10
  185. package/build/en-json.1f137a90.chunk.js +0 -1
  186. package/build/es-json.e275481d.chunk.js +0 -1
  187. package/build/main.7b151630.js +0 -4377
  188. package/build/ms-json.db87d8d3.chunk.js +0 -1
  189. package/build/pt-json.62927d1e.chunk.js +0 -1
  190. package/build/runtime~main.a20d633b.js +0 -2
  191. package/build/uk-json.b2fcd567.chunk.js +0 -1
  192. package/build/upload-settings.ef64bbf9.chunk.js +0 -84
  193. package/build/upload.c5730dfa.chunk.js +0 -33
  194. package/build/vi-json.f08d7d03.chunk.js +0 -1
  195. package/build/webhook-edit-page.73e51e64.chunk.js +0 -75
  196. package/build/webhook-list-page.1134f130.chunk.js +0 -42
@@ -1,92 +1,91 @@
1
- import React, { useState } from 'react';
1
+ import React, { useRef, useState } from 'react';
2
2
  import styled from 'styled-components';
3
3
  import { useIntl } from 'react-intl';
4
- import { Box, Flex, FocusTrap, Typography, Icon, Stack } from '@strapi/design-system';
5
- import { Book, Cross, Information, Question } from '@strapi/icons';
6
- import { pxToRem } from '@strapi/helper-plugin';
7
-
8
- import { useConfigurations } from '../../../hooks';
9
-
10
- const OnboardingWrapper = styled(Box)`
11
- position: fixed;
12
- bottom: ${({ theme }) => theme.spaces[2]};
13
- right: ${({ theme }) => theme.spaces[2]};
14
- `;
15
-
16
- const Button = styled(Box)`
17
- width: ${({ theme }) => theme.spaces[8]};
18
- height: ${({ theme }) => theme.spaces[8]};
19
- background: ${({ theme }) => theme.colors.primary600};
20
- box-shadow: ${({ theme }) => theme.shadows.tableShadow};
4
+ import {
5
+ Box,
6
+ Button,
7
+ Divider,
8
+ Flex,
9
+ FocusTrap,
10
+ Icon,
11
+ Portal,
12
+ PopoverPrimitives,
13
+ Stack,
14
+ Typography,
15
+ VisuallyHidden,
16
+ } from '@strapi/design-system';
17
+ import { Cross, Play, Question } from '@strapi/icons';
18
+
19
+ import onboardingPreview from '../../../assets/images/onboarding-preview.png';
20
+ import { VIDEO_LINKS, DOCUMENTATION_LINKS, WATCH_MORE } from './constants';
21
+
22
+ // TODO: use new Button props derived from Box props with next DS release
23
+ const HelperButton = styled(Button)`
21
24
  border-radius: 50%;
22
-
23
- svg path {
24
- fill: ${({ theme }) => theme.colors.buttonNeutral0};
25
- }
25
+ padding: ${({ theme }) => theme.spaces[3]};
26
+ /* Resetting 2rem height defined by Button component */
27
+ height: 100%;
26
28
  `;
27
29
 
28
- const LinksWrapper = styled(Box)`
29
- bottom: ${({ theme }) => `${theme.spaces[9]}`};
30
- min-width: ${200 / 16}rem;
31
- position: absolute;
32
- right: 0;
30
+ const IconWrapper = styled(Flex)`
31
+ transform: translate(-50%, -50%);
33
32
  `;
34
33
 
35
- const StyledLink = styled(Flex)`
34
+ const VideoLinkWrapper = styled(Flex)`
36
35
  text-decoration: none;
37
36
 
38
- svg path {
39
- fill: ${({ theme }) => theme.colors.neutral600};
37
+ :focus-visible {
38
+ outline-offset: ${({ theme }) => `-${theme.spaces[1]}`};
40
39
  }
41
40
 
42
- &:focus,
43
- &:hover {
44
- background: ${({ theme }) => theme.colors.neutral100};
41
+ :hover {
42
+ background: ${({ theme }) => theme.colors.primary100};
45
43
 
46
- svg path {
47
- fill: ${({ theme }) => theme.colors.neutral700};
44
+ /* Hover style for the number displayed */
45
+ ${Typography}:first-child {
46
+ color: ${({ theme }) => theme.colors.primary500};
48
47
  }
49
48
 
50
- ${[Typography]} {
51
- color: ${({ theme }) => theme.colors.neutral700};
49
+ /* Hover style for the label */
50
+ ${Typography}:nth-child(1) {
51
+ color: ${({ theme }) => theme.colors.primary600};
52
52
  }
53
53
  }
54
54
  `;
55
55
 
56
+ const Preview = styled.img`
57
+ width: ${({ theme }) => theme.spaces[10]};
58
+ height: ${({ theme }) => theme.spaces[8]};
59
+ /* Same overlay used in ModalLayout */
60
+ background: ${({ theme }) => `${theme.colors.neutral800}1F`};
61
+ border-radius: ${({ theme }) => theme.borderRadius};
62
+ `;
63
+
64
+ const TypographyLineHeight = styled(Typography)`
65
+ /* line height of label and watch more to 1 so they can be better aligned visually */
66
+ line-height: 1;
67
+ `;
68
+
69
+ const TextLink = styled(TypographyLineHeight)`
70
+ text-decoration: none;
71
+
72
+ :hover {
73
+ text-decoration: underline;
74
+ }
75
+ `;
76
+
56
77
  const Onboarding = () => {
78
+ const triggerRef = useRef();
57
79
  const [isOpen, setIsOpen] = useState(false);
58
80
  const { formatMessage } = useIntl();
59
- const { showTutorials } = useConfigurations();
60
-
61
- if (!showTutorials) {
62
- return null;
63
- }
64
81
 
65
- const STATIC_LINKS = [
66
- {
67
- Icon: <Book />,
68
- label: formatMessage({
69
- id: 'global.documentation',
70
- defaultMessage: 'Documentation',
71
- }),
72
- destination: 'https://docs.strapi.io',
73
- },
74
- {
75
- Icon: <Information />,
76
- label: formatMessage({ id: 'app.static.links.cheatsheet', defaultMessage: 'CheatSheet' }),
77
- destination: 'https://strapi-showcase.s3-us-west-2.amazonaws.com/CheatSheet.pdf',
78
- },
79
- ];
80
-
81
- const handleClick = () => {
82
+ const handlePopoverVisibility = () => {
82
83
  setIsOpen((prev) => !prev);
83
84
  };
84
85
 
85
86
  return (
86
- <OnboardingWrapper as="aside">
87
- <Button
88
- as="button"
89
- id="onboarding"
87
+ <Box as="aside" position="fixed" bottom={2} right={2}>
88
+ <HelperButton
90
89
  aria-label={formatMessage(
91
90
  isOpen
92
91
  ? {
@@ -98,37 +97,110 @@ const Onboarding = () => {
98
97
  defaultMessage: 'Open help menu',
99
98
  }
100
99
  )}
101
- onClick={handleClick}
100
+ onClick={handlePopoverVisibility}
101
+ ref={triggerRef}
102
102
  >
103
- <Icon as={isOpen ? Cross : Question} height={pxToRem(16)} width={pxToRem(16)} />
104
- </Button>
103
+ <Icon as={isOpen ? Cross : Question} color="buttonNeutral0" />
104
+ </HelperButton>
105
105
 
106
- {/* FIX ME - replace with popover when overflow popover is fixed
107
- + when v4 mockups for onboarding component are ready */}
108
106
  {isOpen && (
109
- <FocusTrap onEscape={handleClick}>
110
- <LinksWrapper background="neutral0" hasRadius shadow="tableShadow" padding={2}>
111
- {STATIC_LINKS.map((link) => (
112
- <StyledLink
113
- as="a"
114
- key={link.label}
115
- rel="nofollow noreferrer noopener"
116
- target="_blank"
117
- href={link.destination}
118
- padding={2}
119
- hasRadius
120
- alignItems="center"
107
+ <Portal>
108
+ <PopoverPrimitives.Content
109
+ padding={0}
110
+ source={triggerRef}
111
+ placement="top-end"
112
+ spacing={12}
113
+ >
114
+ <FocusTrap onEscape={handlePopoverVisibility}>
115
+ <Flex
116
+ justifyContent="space-between"
117
+ paddingBottom={5}
118
+ paddingRight={6}
119
+ paddingLeft={6}
120
+ paddingTop={6}
121
121
  >
122
- <Stack horizontal spacing={2}>
123
- {link.Icon}
124
- <Typography color="neutral600">{link.label}</Typography>
125
- </Stack>
126
- </StyledLink>
127
- ))}
128
- </LinksWrapper>
129
- </FocusTrap>
122
+ <TypographyLineHeight fontWeight="bold">
123
+ {formatMessage({
124
+ id: 'app.components.Onboarding.title',
125
+ defaultMessage: 'Get started videos',
126
+ })}
127
+ </TypographyLineHeight>
128
+ <TextLink
129
+ as="a"
130
+ href={WATCH_MORE.href}
131
+ target="_blank"
132
+ rel="noreferrer noopener"
133
+ variant="pi"
134
+ textColor="primary600"
135
+ >
136
+ {formatMessage(WATCH_MORE.label)}
137
+ </TextLink>
138
+ </Flex>
139
+ <Divider />
140
+ {VIDEO_LINKS.map(({ href, duration, label }, index) => (
141
+ <VideoLinkWrapper
142
+ as="a"
143
+ href={href}
144
+ target="_blank"
145
+ rel="noreferrer noopener"
146
+ key={href}
147
+ hasRadius
148
+ paddingTop={4}
149
+ paddingBottom={4}
150
+ paddingLeft={6}
151
+ paddingRight={11}
152
+ >
153
+ <Box paddingRight={5}>
154
+ <Typography textColor="neutral200" variant="alpha">
155
+ {index + 1}
156
+ </Typography>
157
+ </Box>
158
+ <Box position="relative">
159
+ <Preview src={onboardingPreview} alt="" />
160
+ <IconWrapper
161
+ position="absolute"
162
+ top="50%"
163
+ left="50%"
164
+ background="primary600"
165
+ borderRadius="50%"
166
+ justifyContent="center"
167
+ width={6}
168
+ height={6}
169
+ >
170
+ <Icon as={Play} color="buttonNeutral0" width={3} height={3} />
171
+ </IconWrapper>
172
+ </Box>
173
+ <Flex direction="column" alignItems="start" paddingLeft={4}>
174
+ <Typography fontWeight="bold">{formatMessage(label)}</Typography>
175
+ <VisuallyHidden>:</VisuallyHidden>
176
+ <Typography textColor="neutral600" variant="pi">
177
+ {duration}
178
+ </Typography>
179
+ </Flex>
180
+ </VideoLinkWrapper>
181
+ ))}
182
+ <Stack spacing={2} paddingLeft={5} paddingTop={2} paddingBottom={5}>
183
+ {DOCUMENTATION_LINKS.map(({ label, href, icon }) => (
184
+ <Stack horizontal spacing={3} key={href}>
185
+ <Icon as={icon} color="primary600" />
186
+ <TextLink
187
+ as="a"
188
+ href={href}
189
+ target="_blank"
190
+ rel="noreferrer noopener"
191
+ variant="sigma"
192
+ textColor="primary700"
193
+ >
194
+ {formatMessage(label)}
195
+ </TextLink>
196
+ </Stack>
197
+ ))}
198
+ </Stack>
199
+ </FocusTrap>
200
+ </PopoverPrimitives.Content>
201
+ </Portal>
130
202
  )}
131
- </OnboardingWrapper>
203
+ </Box>
132
204
  );
133
205
  };
134
206
 
@@ -10,10 +10,11 @@ import { useTracking, LoadingIndicatorPage, useStrapiApp } from '@strapi/helper-
10
10
  import { useDispatch, useSelector } from 'react-redux';
11
11
  import { DndProvider } from 'react-dnd';
12
12
  import { HTML5Backend } from 'react-dnd-html5-backend';
13
+
13
14
  import GuidedTourModal from '../../components/GuidedTour/Modal';
14
15
  import LeftMenu from '../../components/LeftMenu';
15
16
  import AppLayout from '../../layouts/AppLayout';
16
- import { useMenu } from '../../hooks';
17
+ import { useMenu, useConfigurations } from '../../hooks';
17
18
  import { createRoute } from '../../utils';
18
19
  import { SET_APP_RUNTIME_STATUS } from '../App/constants';
19
20
  import Onboarding from './Onboarding';
@@ -65,6 +66,7 @@ const Admin = () => {
65
66
  useTrackUsage();
66
67
  const { isLoading, generalSectionLinks, pluginsSectionLinks } = useMenu();
67
68
  const { menu } = useStrapiApp();
69
+ const { showTutorials } = useConfigurations();
68
70
 
69
71
  const routes = useMemo(() => {
70
72
  return menu
@@ -106,7 +108,8 @@ const Admin = () => {
106
108
  </Switch>
107
109
  </Suspense>
108
110
  <GuidedTourModal />
109
- <Onboarding />
111
+
112
+ {showTutorials && <Onboarding />}
110
113
  </AppLayout>
111
114
  </DndProvider>
112
115
  );
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
- import { NavLink } from 'react-router-dom';
2
+ import { NavLink, useLocation } from 'react-router-dom';
3
3
  import { useIntl } from 'react-intl';
4
4
  import PropTypes from 'prop-types';
5
+ import { useTracking } from '@strapi/helper-plugin';
5
6
  import {
6
7
  SubNav,
7
8
  SubNavHeader,
@@ -13,6 +14,8 @@ import { getSectionsToDisplay } from '../../utils';
13
14
 
14
15
  const SettingsNav = ({ menu }) => {
15
16
  const { formatMessage } = useIntl();
17
+ const { trackUsage } = useTracking();
18
+ const { pathname } = useLocation();
16
19
 
17
20
  const filteredMenu = getSectionsToDisplay(menu);
18
21
 
@@ -35,6 +38,10 @@ const SettingsNav = ({ menu }) => {
35
38
  defaultMessage: 'Settings',
36
39
  });
37
40
 
41
+ const handleClickOnLink = (destination = null) => {
42
+ trackUsage('willNavigate', { from: pathname, to: destination });
43
+ };
44
+
38
45
  return (
39
46
  <SubNav ariaLabel={label}>
40
47
  <SubNavHeader label={label} />
@@ -42,7 +49,13 @@ const SettingsNav = ({ menu }) => {
42
49
  {sections.map((section) => (
43
50
  <SubNavSection key={section.id} label={formatMessage(section.intlLabel)}>
44
51
  {section.links.map((link) => (
45
- <SubNavLink as={NavLink} withBullet={link.hasNotification} to={link.to} key={link.id}>
52
+ <SubNavLink
53
+ as={NavLink}
54
+ withBullet={link.hasNotification}
55
+ to={link.to}
56
+ onClick={() => handleClickOnLink(link.to)}
57
+ key={link.id}
58
+ >
46
59
  {formatMessage(link.intlLabel)}
47
60
  </SubNavLink>
48
61
  ))}
@@ -1,28 +1,11 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { IconButton } from '@strapi/design-system/IconButton';
3
+ import { IconButton } from '@strapi/design-system';
4
4
  import { useNotification, ContentBox } from '@strapi/helper-plugin';
5
- import Duplicate from '@strapi/icons/Duplicate';
5
+ import { Duplicate } from '@strapi/icons';
6
6
  import { CopyToClipboard } from 'react-copy-to-clipboard';
7
7
  import { useIntl } from 'react-intl';
8
8
 
9
- // FIXME replace with parts when ready
10
- const Envelope = () => (
11
- <svg xmlns="http://www.w3.org/2000/svg">
12
- <text
13
- transform="translate(-23 -9)"
14
- fill="#4B515A"
15
- fillRule="evenodd"
16
- fontSize="32"
17
- fontFamily="AppleColorEmoji, Apple Color Emoji"
18
- >
19
- <tspan x="23" y="36">
20
- ✉️
21
- </tspan>
22
- </text>
23
- </svg>
24
- );
25
-
26
9
  const MagicLinkWrapper = ({ children, target }) => {
27
10
  const toggleNotification = useNotification();
28
11
  const { formatMessage } = useIntl();
@@ -46,7 +29,7 @@ const MagicLinkWrapper = ({ children, target }) => {
46
29
  title={target}
47
30
  titleEllipsis
48
31
  subtitle={children}
49
- icon={<Envelope />}
32
+ icon={<span style={{ fontSize: 32 }}>✉️</span>}
50
33
  iconBackground="neutral100"
51
34
  />
52
35
  );
@@ -21,23 +21,10 @@ const permissions = {
21
21
  ],
22
22
  },
23
23
  marketplace: {
24
- main: [
25
- { action: 'admin::marketplace.read', subject: null },
26
- { action: 'admin::marketplace.plugins.install', subject: null },
27
- { action: 'admin::marketplace.plugins.uninstall', subject: null },
28
- ],
29
- install: [{ action: 'admin::marketplace.plugins.install', subject: null }],
30
- read: [
31
- { action: 'admin::marketplace.read', subject: null },
32
- { action: 'admin::marketplace.plugins.uninstall', subject: null },
33
- ],
34
- uninstall: [{ action: 'admin::marketplace.plugins.uninstall', subject: null }],
24
+ main: [{ action: 'admin::marketplace.read', subject: null }],
25
+ read: [{ action: 'admin::marketplace.read', subject: null }],
35
26
  },
36
27
  settings: {
37
- auditLogs: {
38
- main: [{ action: 'admin::audit-logs.read', subject: null }],
39
- read: [{ action: 'admin::audit-logs.read', subject: null }],
40
- },
41
28
  roles: {
42
29
  main: [
43
30
  { action: 'admin::roles.create', subject: null },
@@ -90,10 +90,10 @@
90
90
  "components.Input.error.password.noMatch": "كلمات السر لا تتطابق",
91
91
  "components.Input.error.validation.email": "هذا ليس بريد الإكتروني",
92
92
  "components.Input.error.validation.json": "لا يتطابق مع صيغة JSON",
93
- "components.Input.error.validation.max": "هذه القيمة عالية جدًا.",
94
- "components.Input.error.validation.maxLength": "هذه القيمة طويلة جدًا.",
95
- "components.Input.error.validation.min": "هذه القيمة قليلة جدًا.",
96
- "components.Input.error.validation.minLength": "هذه القيمة قصيرة جدًا.",
93
+ "components.Input.error.validation.max": "هذه القيمة عالية جدًا {max}.",
94
+ "components.Input.error.validation.maxLength": "هذه القيمة طويلة جدًا {max}.",
95
+ "components.Input.error.validation.min": "هذه القيمة قليلة جدًا {min}.",
96
+ "components.Input.error.validation.minLength": "هذه القيمة قصيرة جدًا {min}.",
97
97
  "components.Input.error.validation.minSupMax": "لا يمكن أن تكون متفوقة",
98
98
  "components.Input.error.validation.regex": "هذه القمية لا تطابق regex.",
99
99
  "components.Input.error.validation.required": "هذه القيمة مطلوبة.",
@@ -409,10 +409,10 @@
409
409
  "components.Input.error.validation.email": "Això no és un email",
410
410
  "components.Input.error.validation.json": "Això no coincideix amb el format JSON",
411
411
  "components.Input.error.validation.lowercase": "El valor ha de ser una cadena en minúscules",
412
- "components.Input.error.validation.max": "El valor és massa alt.",
413
- "components.Input.error.validation.maxLength": "El valor és massa llarg.",
414
- "components.Input.error.validation.min": "El valor és massa baix.",
415
- "components.Input.error.validation.minLength": "El valor és massa curt.",
412
+ "components.Input.error.validation.max": "El valor és massa alt {max}.",
413
+ "components.Input.error.validation.maxLength": "El valor és massa llarg {max}.",
414
+ "components.Input.error.validation.min": "El valor és massa baix {min}.",
415
+ "components.Input.error.validation.minLength": "El valor és massa curt {min}.",
416
416
  "components.Input.error.validation.minSupMax": "No pot ser superior",
417
417
  "components.Input.error.validation.regex": "El valor no coincideix amb el de regex.",
418
418
  "components.Input.error.validation.required": "Aquest valor és obligatori.",
@@ -115,10 +115,10 @@
115
115
  "components.Input.error.password.noMatch": "Hesla se neshodují",
116
116
  "components.Input.error.validation.email": "Toto není e-mailová adresa",
117
117
  "components.Input.error.validation.json": "Toto se neshoduje s formátem JSON",
118
- "components.Input.error.validation.max": "Hodnota je příliš vysoká.",
119
- "components.Input.error.validation.maxLength": "Hodnota je příliš dlouhá.",
120
- "components.Input.error.validation.min": "Hodnota je příliš nízká.",
121
- "components.Input.error.validation.minLength": "Hodnota je příliš krátká.",
118
+ "components.Input.error.validation.max": "Hodnota je příliš vysoká {max}.",
119
+ "components.Input.error.validation.maxLength": "Hodnota je příliš dlouhá {max}.",
120
+ "components.Input.error.validation.min": "Hodnota je příliš nízká {min}.",
121
+ "components.Input.error.validation.minLength": "Hodnota je příliš krátká {min}.",
122
122
  "components.Input.error.validation.minSupMax": "Nemůže být nadřazený",
123
123
  "components.Input.error.validation.regex": "Hodnota neodpovídá požadovanému vzoru.",
124
124
  "components.Input.error.validation.required": "Tato hodnota je povinná.",
@@ -405,10 +405,10 @@
405
405
  "components.Input.error.validation.email": "Das ist keine gültige E-Mail-Adresse",
406
406
  "components.Input.error.validation.json": "Dies entspricht nicht dem JSON-Format.",
407
407
  "components.Input.error.validation.lowercase": "Dieser Wert muss kleingeschreiben sein.",
408
- "components.Input.error.validation.max": "Dieser Wert ist zu hoch.",
409
- "components.Input.error.validation.maxLength": "Dieser Wert ist zu lang.",
410
- "components.Input.error.validation.min": "Dieser Wert ist zu niedrig.",
411
- "components.Input.error.validation.minLength": "Dieser Wert ist zu kurz.",
408
+ "components.Input.error.validation.max": "Dieser Wert ist zu hoch {max}.",
409
+ "components.Input.error.validation.maxLength": "Dieser Wert ist zu lang {max}.",
410
+ "components.Input.error.validation.min": "Dieser Wert ist zu niedrig {min}.",
411
+ "components.Input.error.validation.minLength": "Dieser Wert ist zu kurz {min}.",
412
412
  "components.Input.error.validation.minSupMax": "Darf nicht höher sein",
413
413
  "components.Input.error.validation.regex": "Dieser Wert entspricht nicht dem RegEx.",
414
414
  "components.Input.error.validation.required": "Die Eingabe dieses Wertes ist erforderlich.",
@@ -353,10 +353,10 @@
353
353
  "components.Input.error.password.noMatch": "Kodeord er ikke ens",
354
354
  "components.Input.error.validation.email": "Dette er ikke en e-mail",
355
355
  "components.Input.error.validation.json": "Dette matcher ikke JSON formatet",
356
- "components.Input.error.validation.max": "Værdien er for høj.",
357
- "components.Input.error.validation.maxLength": "Værdien er for lang.",
358
- "components.Input.error.validation.min": "Værdien er for lav.",
359
- "components.Input.error.validation.minLength": "Værdien er for kort.",
356
+ "components.Input.error.validation.max": "Værdien er for høj {max}.",
357
+ "components.Input.error.validation.maxLength": "Værdien er for lang {max}.",
358
+ "components.Input.error.validation.min": "Værdien er for lav {min}.",
359
+ "components.Input.error.validation.minLength": "Værdien er for kort {min}.",
360
360
  "components.Input.error.validation.minSupMax": "Kan ikke være højere",
361
361
  "components.Input.error.validation.regex": "Værdien matcher ikke regex.",
362
362
  "components.Input.error.validation.required": "Værdien er påkrævet.",
@@ -226,6 +226,11 @@
226
226
  "Settings.profile.form.section.experience.title": "Experience",
227
227
  "Settings.profile.form.section.helmet.title": "User profile",
228
228
  "Settings.profile.form.section.profile.page.title": "Profile page",
229
+ "Settings.review-workflows.page.title": "Review Workflows",
230
+ "Settings.review-workflows.page.subtitle": "{count, plural, one {# stage} other {# stages}}",
231
+ "Settings.review-workflows.page.isLoading": "Workflow is loading",
232
+ "Settings.review-workflows.page.delete.confirm.body": "All entries assigned to deleted stages will be moved to the first stage. Are you sure you want to save this?",
233
+ "Settings.review-workflows.stage.name.label": "Stage name",
229
234
  "Settings.roles.create.description": "Define the rights given to the role",
230
235
  "Settings.roles.create.title": "Create a role",
231
236
  "Settings.roles.created": "Role created",
@@ -433,7 +438,11 @@
433
438
  "app.components.Official": "Official",
434
439
  "app.components.Onboarding.help.button": "Help button",
435
440
  "app.components.Onboarding.label.completed": "% completed",
436
- "app.components.Onboarding.title": "Get Started Videos",
441
+ "app.components.Onboarding.title": "Get started videos",
442
+ "app.components.Onboarding.link.more-videos": "Watch more videos",
443
+ "app.components.Onboarding.link.build-content": "Build a content architecture",
444
+ "app.components.Onboarding.link.manage-content": "Add & manage content",
445
+ "app.components.Onboarding.link.manage-media": "Manage media",
437
446
  "app.components.PluginCard.Button.label.download": "Download",
438
447
  "app.components.PluginCard.Button.label.install": "Already installed",
439
448
  "app.components.PluginCard.PopUpWarning.install.impossible.autoReload.needed": "The autoReload feature needs to be enabled. Please start your app with `yarn develop`.",
@@ -528,10 +537,10 @@
528
537
  "components.Input.error.validation.email": "Value is an invalid email",
529
538
  "components.Input.error.validation.json": "Value is invalid JSON",
530
539
  "components.Input.error.validation.lowercase": "The value must be a lowercase string",
531
- "components.Input.error.validation.max": "Value is larger than the maximum",
532
- "components.Input.error.validation.maxLength": "Value is longer than the maximum",
533
- "components.Input.error.validation.min": "Value is smaller than the minimum",
534
- "components.Input.error.validation.minLength": "Value is shorter than the minimum",
540
+ "components.Input.error.validation.max": "Value is larger than the maximum {max}",
541
+ "components.Input.error.validation.maxLength": "Value is longer than the maximum length {max}",
542
+ "components.Input.error.validation.min": "Value is smaller than the minimum {min}",
543
+ "components.Input.error.validation.minLength": "Value is shorter than the minimum length {min}",
535
544
  "components.Input.error.validation.minSupMax": "Value cannot be superior",
536
545
  "components.Input.error.validation.regex": "Value does not match the required pattern",
537
546
  "components.Input.error.validation.required": "Value is required",
@@ -353,10 +353,10 @@
353
353
  "components.Input.error.password.noMatch": "Las contraseñas no coinciden",
354
354
  "components.Input.error.validation.email": "Esto no es un email",
355
355
  "components.Input.error.validation.json": "Esto no coincide con el formato JSON",
356
- "components.Input.error.validation.max": "El valor es demasiado alto.",
357
- "components.Input.error.validation.maxLength": "El valor es demasiado largo.",
358
- "components.Input.error.validation.min": "El valor es demasiado bajo.",
359
- "components.Input.error.validation.minLength": "El valor es demasiado corto.",
356
+ "components.Input.error.validation.max": "El valor es demasiado alto {max}.",
357
+ "components.Input.error.validation.maxLength": "El valor es demasiado largo {max}.",
358
+ "components.Input.error.validation.min": "El valor es demasiado bajo {min}.",
359
+ "components.Input.error.validation.minLength": "El valor es demasiado corto {min}.",
360
360
  "components.Input.error.validation.minSupMax": "No puede ser superior",
361
361
  "components.Input.error.validation.regex": "El valor no coincide con el de regex.",
362
362
  "components.Input.error.validation.required": "Este valor es obligatorio.",
@@ -489,10 +489,10 @@
489
489
  "components.Input.error.validation.email": "Posta elektroniko hau ez da baliozkoa.",
490
490
  "components.Input.error.validation.json": "Hau ez dator bat JSON formatuarekin",
491
491
  "components.Input.error.validation.lowercase": "Balioa minuskulazko kate bat izan behar da",
492
- "components.Input.error.validation.max": "Balioa handiegia da.",
493
- "components.Input.error.validation.maxLength": "Balioa luzeegia da.",
494
- "components.Input.error.validation.min": "Balioa txikiegia da.",
495
- "components.Input.error.validation.minLength": "Balioa laburregia da.",
492
+ "components.Input.error.validation.max": "Balioa handiegia da {max}.",
493
+ "components.Input.error.validation.maxLength": "Balioa luzeegia da {max}.",
494
+ "components.Input.error.validation.min": "Balioa txikiegia da {min}.",
495
+ "components.Input.error.validation.minLength": "Balioa laburregia da {min}.",
496
496
  "components.Input.error.validation.minSupMax": "Ezin da handiagoa izan.",
497
497
  "components.Input.error.validation.regex": "Balioa ez dator bat regex-arekin.",
498
498
  "components.Input.error.validation.required": "Balio hau beharrezkoa da.",
@@ -353,10 +353,10 @@
353
353
  "components.Input.error.password.noMatch": "Le mot de passe ne correspond pas",
354
354
  "components.Input.error.validation.email": "Le format n'est pas de type e-mail",
355
355
  "components.Input.error.validation.json": "Le format JSON n'est pas respecté",
356
- "components.Input.error.validation.max": "La valeur est trop grande.",
357
- "components.Input.error.validation.maxLength": "La valeur est trop longue.",
358
- "components.Input.error.validation.min": "La valeur est trop basse.",
359
- "components.Input.error.validation.minLength": "La valeur est trop courte.",
356
+ "components.Input.error.validation.max": "La valeur est trop grande {max}.",
357
+ "components.Input.error.validation.maxLength": "La valeur est trop longue {max}.",
358
+ "components.Input.error.validation.min": "La valeur est trop basse {min}.",
359
+ "components.Input.error.validation.minLength": "La valeur est trop courte {min}.",
360
360
  "components.Input.error.validation.minSupMax": "Ne peut pas être plus grand.",
361
361
  "components.Input.error.validation.regex": "La valeur ne correspond pas au format attendu.",
362
362
  "components.Input.error.validation.required": "Ce champ est obligatoire.",
@@ -328,10 +328,10 @@
328
328
  "components.Input.error.validation.email": "આ અમાન્ય ઈમેલ છે",
329
329
  "components.Input.error.validation.json": "આ JSON ફોર્મેટ સાથે મેળ ખાતું નથી",
330
330
  "components.Input.error.validation.lowercase": "મૂલ્ય લોઅરકેસ સ્ટ્રિંગ હોવી જોઈએ",
331
- "components.Input.error.validation.max": "મૂલ્ય ખૂબ વધારે છે.",
332
- "components.Input.error.validation.maxLength": "મૂલ્ય ખૂબ લાંબુ છે.",
333
- "components.Input.error.validation.min": "મૂલ્ય ખૂબ ઓછું છે.",
334
- "components.Input.error.validation.minLength": "મૂલ્ય ખૂબ ટૂંકું છે.",
331
+ "components.Input.error.validation.max": "મૂલ્ય ખૂબ વધારે છે {max}.",
332
+ "components.Input.error.validation.maxLength": "મૂલ્ય ખૂબ લાંબુ છે {max}.",
333
+ "components.Input.error.validation.min": "મૂલ્ય ખૂબ ઓછું છે {min}.",
334
+ "components.Input.error.validation.minLength": "મૂલ્ય ખૂબ ટૂંકું છે {min}.",
335
335
  "components.Input.error.validation.minSupMax": "બહેતર ન હોઈ શકે",
336
336
  "components.Input.error.validation.regex": "મૂલ્ય રેગેક્સ સાથે મેળ ખાતું નથી.",
337
337
  "components.Input.error.validation.required": "આ મૂલ્ય જરૂરી છે.",
@@ -256,10 +256,10 @@
256
256
  "components.Input.error.password.noMatch": "הסיסמאות לא תואמות",
257
257
  "components.Input.error.validation.email": "זה לא דוא\"ל",
258
258
  "components.Input.error.validation.json": "זה לא תואם לפורמט JSON",
259
- "components.Input.error.validation.max": "הערך גבוה מדי.",
260
- "components.Input.error.validation.maxLength": "הערך ארוך מדי.",
261
- "components.Input.error.validation.min": "הערך נמוך מדי.",
262
- "components.Input.error.validation.minLength": "הערך קצר מדי.",
259
+ "components.Input.error.validation.max": "הערך גבוה מדי {max}.",
260
+ "components.Input.error.validation.maxLength": "הערך ארוך מדי {max}.",
261
+ "components.Input.error.validation.min": "הערך נמוך מדי {min}.",
262
+ "components.Input.error.validation.minLength": "הערך קצר מדי {min}.",
263
263
  "components.Input.error.validation.minSupMax": "לא יכול להיות מעולה",
264
264
  "components.Input.error.validation.regex": "הערך אינו תואם את ה- regex.",
265
265
  "components.Input.error.validation.required": "ערך זה נדרש.",