strapi-plugin-comments 1.0.4 → 2.0.0-beta.4

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 (156) hide show
  1. package/.circleci/config.yml +2 -2
  2. package/README.md +53 -126
  3. package/admin/src/components/ConfirmationDialog/index.js +56 -0
  4. package/admin/src/components/DiscussionStatus/index.js +33 -0
  5. package/admin/src/components/DiscussionThread/index.js +59 -0
  6. package/admin/src/components/DiscussionThreadItem/index.js +87 -0
  7. package/admin/src/components/DiscussionThreadItem/styles.js +88 -0
  8. package/admin/src/components/DiscussionThreadItemActions/index.js +178 -0
  9. package/admin/src/components/DiscussionThreadItemActions/styles.js +22 -0
  10. package/admin/src/components/DiscussionThreadItemMeta/index.js +31 -0
  11. package/admin/src/components/DiscussionThreadItemWarnings/index.js +141 -0
  12. package/admin/src/components/DiscussionThreadItemWarnings/styles.js +7 -0
  13. package/admin/src/components/EntityDetails/index.js +53 -0
  14. package/admin/src/{containers → components}/Initializer/index.js +4 -4
  15. package/admin/src/components/LoadingIndicatorOverlay/index.js +15 -0
  16. package/admin/src/components/LoadingIndicatorOverlay/styles.js +20 -0
  17. package/admin/src/components/Nav/index.js +45 -0
  18. package/admin/src/components/PluginIcon/index.js +12 -0
  19. package/admin/src/components/ReportsReviewModal/index.js +43 -0
  20. package/admin/src/components/ReportsReviewTable/index.js +146 -0
  21. package/admin/src/components/TableFilters/index.js +53 -0
  22. package/admin/src/components/TablePagination/index.js +35 -0
  23. package/admin/src/components/icons/comments.js +9 -0
  24. package/admin/src/components/icons/index.js +6 -0
  25. package/admin/src/components/icons/lock.js +22 -0
  26. package/admin/src/components/icons/review.js +18 -0
  27. package/admin/src/components/icons/unlock.js +20 -0
  28. package/admin/src/index.js +58 -42
  29. package/admin/src/pages/App/index.js +71 -0
  30. package/admin/src/pages/App/reducer/actions.js +8 -0
  31. package/admin/src/pages/App/reducer/constants.js +4 -0
  32. package/admin/src/pages/App/reducer/index.js +26 -0
  33. package/admin/src/pages/App/reducer/init.js +7 -0
  34. package/admin/src/pages/App/reducer/selectors.js +35 -0
  35. package/admin/src/pages/App/utils/api.js +12 -0
  36. package/admin/src/pages/ComingSoonPage/index.js +25 -0
  37. package/admin/src/pages/Details/index.js +109 -0
  38. package/admin/src/pages/Details/utils/api.js +41 -0
  39. package/admin/src/pages/Discover/components/DiscoverTableRow/index.js +196 -0
  40. package/admin/src/pages/Discover/index.js +157 -0
  41. package/admin/src/pages/Discover/utils/api.js +14 -0
  42. package/admin/src/pages/Discover/utils/filtersSchema.js +9 -0
  43. package/admin/src/permissions.js +13 -37
  44. package/admin/src/pluginId.js +2 -4
  45. package/admin/src/reducers.js +8 -0
  46. package/admin/src/translations/en.json +73 -37
  47. package/admin/src/translations/fr.json +1 -0
  48. package/admin/src/utils/axiosInstance.js +35 -0
  49. package/admin/src/utils/constants.js +25 -6
  50. package/admin/src/utils/getApiUrl.js +5 -0
  51. package/admin/src/utils/getMessage.js +21 -0
  52. package/admin/src/utils/getRelatedGroups.js +5 -0
  53. package/admin/src/utils/getUrl.js +5 -0
  54. package/admin/src/utils/handleAPIError.js +15 -0
  55. package/admin/src/utils/index.js +6 -0
  56. package/codecov.yml +2 -1
  57. package/content-types/comment.js +97 -0
  58. package/content-types/index.js +11 -0
  59. package/content-types/report.js +54 -0
  60. package/package.json +11 -25
  61. package/server/bootstrap.js +5 -0
  62. package/server/config/index.js +10 -0
  63. package/server/controllers/admin.js +134 -0
  64. package/server/controllers/client.js +117 -0
  65. package/server/controllers/index.js +9 -0
  66. package/{controllers → server/controllers}/utils/__tests__/functions.test.js +0 -0
  67. package/{controllers → server/controllers}/utils/functions.js +1 -1
  68. package/server/destroy.js +5 -0
  69. package/server/index.js +22 -0
  70. package/server/register.js +5 -0
  71. package/server/routes/admin.js +92 -0
  72. package/server/routes/client.js +52 -0
  73. package/server/routes/index.js +15 -0
  74. package/server/services/admin.js +215 -0
  75. package/server/services/client.js +227 -0
  76. package/server/services/common.js +197 -0
  77. package/server/services/index.js +11 -0
  78. package/{services → server/services}/utils/__tests__/functions.test.js +0 -0
  79. package/{services → server/services}/utils/functions.js +17 -6
  80. package/server/utils/constants.js +16 -0
  81. package/{services → server}/utils/error.js +0 -0
  82. package/server/utils/functions.js +19 -0
  83. package/strapi-admin.js +3 -0
  84. package/strapi-server.js +9 -0
  85. package/admin/src/assets/images/icon-cross-blue.svg +0 -1
  86. package/admin/src/assets/images/icon_remove.svg +0 -19
  87. package/admin/src/assets/images/logo.svg +0 -5
  88. package/admin/src/components/AbuseReportsPopUp/ItemPreviewContainer.js +0 -8
  89. package/admin/src/components/AbuseReportsPopUp/ModalFooter.js +0 -31
  90. package/admin/src/components/AbuseReportsPopUp/TableContainer.js +0 -63
  91. package/admin/src/components/AbuseReportsPopUp/index.js +0 -148
  92. package/admin/src/components/Container/index.js +0 -7
  93. package/admin/src/components/EmptyView/index.js +0 -25
  94. package/admin/src/components/Filters/index.js +0 -151
  95. package/admin/src/components/Filters/index.styled.js +0 -82
  96. package/admin/src/components/Filters/utils.js +0 -21
  97. package/admin/src/components/Item/CardItem.js +0 -30
  98. package/admin/src/components/Item/CardWrapper.js +0 -10
  99. package/admin/src/components/Item/index.js +0 -107
  100. package/admin/src/components/ItemDetails/CardItem.js +0 -33
  101. package/admin/src/components/ItemDetails/CardLevelCounter.js +0 -46
  102. package/admin/src/components/ItemDetails/CardLevelCounterLink.js +0 -24
  103. package/admin/src/components/ItemDetails/CardLevelWrapper.js +0 -22
  104. package/admin/src/components/ItemDetails/CardWrapper.js +0 -52
  105. package/admin/src/components/ItemDetails/index.js +0 -167
  106. package/admin/src/components/ItemFooter/CardItemAuthor.js +0 -10
  107. package/admin/src/components/ItemFooter/CardItemRelation.js +0 -18
  108. package/admin/src/components/ItemFooter/Wrapper.js +0 -20
  109. package/admin/src/components/ItemFooter/index.js +0 -87
  110. package/admin/src/components/ItemHeader/CardHeaderBlocked.js +0 -24
  111. package/admin/src/components/ItemHeader/CardHeaderIndicator.js +0 -30
  112. package/admin/src/components/ItemHeader/CardHeaderIndicatorBlue.js +0 -11
  113. package/admin/src/components/ItemHeader/CardHeaderIndicatorRed.js +0 -11
  114. package/admin/src/components/ItemHeader/CardHeaderIndicatorsContainer.js +0 -18
  115. package/admin/src/components/ItemHeader/CardHeaderPending.js +0 -11
  116. package/admin/src/components/ItemHeader/CardHeaderReports.js +0 -40
  117. package/admin/src/components/ItemHeader/Wrapper.js +0 -16
  118. package/admin/src/components/ItemHeader/index.js +0 -97
  119. package/admin/src/components/ItemModeration/Wrapper.js +0 -19
  120. package/admin/src/components/ItemModeration/index.js +0 -84
  121. package/admin/src/components/List/Container.js +0 -20
  122. package/admin/src/components/List/index.js +0 -21
  123. package/admin/src/components/Search/index.js +0 -83
  124. package/admin/src/containers/App/Wrapper.js +0 -14
  125. package/admin/src/containers/App/index.js +0 -47
  126. package/admin/src/containers/DataManagerProvider/actions.js +0 -15
  127. package/admin/src/containers/DataManagerProvider/index.js +0 -332
  128. package/admin/src/containers/DataManagerProvider/init.js +0 -5
  129. package/admin/src/containers/DataManagerProvider/reducer.js +0 -59
  130. package/admin/src/containers/DetailsView/Wrapper.js +0 -18
  131. package/admin/src/containers/DetailsView/index.js +0 -106
  132. package/admin/src/containers/ListView/FadedWrapper.js +0 -42
  133. package/admin/src/containers/ListView/Footer.js +0 -53
  134. package/admin/src/containers/ListView/Wrapper.js +0 -17
  135. package/admin/src/containers/ListView/components.js +0 -138
  136. package/admin/src/containers/ListView/index.js +0 -45
  137. package/admin/src/containers/Panel/actions.js +0 -5
  138. package/admin/src/containers/Panel/index.js +0 -191
  139. package/admin/src/containers/Panel/index.styled.js +0 -6
  140. package/admin/src/containers/Panel/reducer.js +0 -44
  141. package/admin/src/contexts/DataManagerContext.js +0 -5
  142. package/admin/src/hooks/useDataManager.js +0 -6
  143. package/admin/src/lifecycles.js +0 -3
  144. package/admin/src/translations/index.js +0 -7
  145. package/admin/src/utils/getTrad.js +0 -5
  146. package/admin/src/utils/getTradId.js +0 -5
  147. package/config/functions/bootstrap.js +0 -62
  148. package/config/routes.json +0 -142
  149. package/config/schema.graphql.js +0 -268
  150. package/controllers/comments.js +0 -228
  151. package/models/comment.js +0 -8
  152. package/models/comment.settings.json +0 -102
  153. package/models/report.js +0 -8
  154. package/models/report.settings.json +0 -49
  155. package/services/comments.js +0 -539
  156. package/services/utils/constants.js +0 -9
@@ -0,0 +1,146 @@
1
+ /**
2
+ *
3
+ * Entity Details
4
+ *
5
+ */
6
+
7
+ import React, { useState, useEffect } from 'react';
8
+ import { useIntl } from 'react-intl';
9
+ import PropTypes from 'prop-types';
10
+ import { isEmpty } from 'lodash';
11
+ import { Badge } from '@strapi/design-system/Badge';
12
+ import { Button } from '@strapi/design-system/Button';
13
+ import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox';
14
+ import { Flex } from '@strapi/design-system/Flex';
15
+ import { Table, Thead, Tbody, TFooter, Tr, Th, Td } from '@strapi/design-system/Table';
16
+ import { Typography } from '@strapi/design-system/Typography';
17
+ import { VisuallyHidden } from '@strapi/design-system/VisuallyHidden';
18
+ import { Check } from '@strapi/icons';
19
+ import { useOverlayBlocker } from '@strapi/helper-plugin';
20
+ import { getMessage } from '../../utils';
21
+ import { REPORT_REASON, REPORT_STATUS } from '../../utils/constants';
22
+
23
+ const ReportsReviewTable = ({
24
+ commentId,
25
+ items,
26
+ mutation,
27
+ onBlockButtonsStateChange,
28
+ }) => {
29
+
30
+ const [storedItems, setStoredItems] = useState([]);
31
+
32
+ const { formatDate } = useIntl();
33
+
34
+ const { lockApp } = useOverlayBlocker();
35
+
36
+ const renderStatus = resolved => {
37
+ const status = resolved ? REPORT_STATUS.RESOLVED : REPORT_STATUS.OPEN;
38
+ let color = 'alternative';
39
+ switch (status) {
40
+ case REPORT_STATUS.RESOLVED:
41
+ color = 'success';
42
+ break;
43
+ case REPORT_STATUS.OPEN:
44
+ color = 'danger';
45
+ };
46
+ return (<Badge backgroundColor={`${color}100`} textColor={`${color}600`}>{ getMessage(`page.details.panel.discussion.warnings.reports.dialog.status.${status}`, status) }</Badge>);
47
+ };
48
+
49
+ const renderReason = reason => {
50
+ let color = 'neutral';
51
+ switch (reason) {
52
+ case REPORT_REASON.DISCRIMINATION:
53
+ color = 'danger';
54
+ break;
55
+ case REPORT_REASON.BAD_LANGUAGE:
56
+ color = 'warning';
57
+ };
58
+ return (<Badge backgroundColor={`${color}100`} textColor={`${color}600`}>{ getMessage(`page.details.panel.discussion.warnings.reports.dialog.reason.${reason}`, reason) }</Badge>);
59
+ };
60
+
61
+ const handleClickResolve = async (reportId) => {
62
+ lockApp();
63
+ const item = await mutation.mutateAsync({
64
+ id: commentId,
65
+ reportId,
66
+ });
67
+ console.log(item);
68
+ if (item) {
69
+ const updatedItems = storedItems.map(_ => ({
70
+ ..._,
71
+ resolved: reportId === _.id ? true : _.resolved,
72
+ }));
73
+ setStoredItems(updatedItems);
74
+ onBlockButtonsStateChange(updatedItems.filter(_ => !_.resolved).length === 0);
75
+ }
76
+ }
77
+
78
+ useEffect(() => {
79
+ setStoredItems(items);
80
+ }, []);
81
+
82
+ if (isEmpty(storedItems)) {
83
+ return null;
84
+ }
85
+
86
+ const COL_COUNT = 6;
87
+
88
+ return (<Table colCount={COL_COUNT} rowCount={storedItems.length}>
89
+ <Thead>
90
+ <Tr>
91
+ <Th>
92
+ <BaseCheckbox aria-label="Select all entries" />
93
+ </Th>
94
+ <Th>
95
+ <Typography variant="sigma">{ getMessage('page.details.panel.discussion.warnings.reports.dialog.reason') }</Typography>
96
+ </Th>
97
+ <Th>
98
+ <Typography variant="sigma">{ getMessage('page.details.panel.discussion.warnings.reports.dialog.content') }</Typography>
99
+ </Th>
100
+ <Th>
101
+ <Typography variant="sigma">{ getMessage('page.details.panel.discussion.warnings.reports.dialog.createdAt') }</Typography>
102
+ </Th>
103
+ <Th>
104
+ <Typography variant="sigma">{ getMessage('page.details.panel.discussion.warnings.reports.dialog.status') }</Typography>
105
+ </Th>
106
+ <Th>
107
+ <VisuallyHidden>{ getMessage('page.details.panel.discussion.warnings.reports.dialog.actions') }</VisuallyHidden>
108
+ </Th>
109
+ </Tr>
110
+ </Thead>
111
+ <Tbody>
112
+ {storedItems.map(entry => <Tr key={entry.id}>
113
+ <Td>
114
+ <BaseCheckbox aria-label={`Select report`} />
115
+ </Td>
116
+ <Td>
117
+ <Typography textColor="neutral800">{renderReason(entry.reason)}</Typography>
118
+ </Td>
119
+ <Td>
120
+ <Typography textColor="neutral800">{entry.content}</Typography>
121
+ </Td>
122
+ <Td>
123
+ <Typography textColor="neutral800">{ formatDate(entry.createdAt, { dateStyle: 'short', timeStyle: 'short' }) }</Typography>
124
+ </Td>
125
+ <Td>
126
+ <Typography textColor="neutral800">{ renderStatus(entry.resolved) }</Typography>
127
+ </Td>
128
+ <Td>
129
+ { !entry.resolved && (<Flex direction="column" alignItems="flex-end">
130
+ <Button onClick={() => handleClickResolve(entry.id)} startIcon={<Check />} variant="success">{ getMessage('page.details.panel.discussion.warnings.reports.dialog.actions.resolve', 'resolve') }</Button>
131
+ </Flex>) }
132
+ </Td>
133
+ </Tr>)}
134
+ </Tbody>
135
+ {/* <TFooter /> */}
136
+ </Table>)
137
+ };
138
+
139
+ ReportsReviewTable.propTypes = {
140
+ commentId: PropTypes.string.isRequired,
141
+ items: PropTypes.array.isRequired,
142
+ mutation: PropTypes.func.isRequired,
143
+ onBlockButtonsStateChange: PropTypes.func.isRequired,
144
+ };
145
+
146
+ export default ReportsReviewTable;
@@ -0,0 +1,53 @@
1
+ import React, { useRef, useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Button } from '@strapi/design-system/Button';
4
+ import { Box } from '@strapi/design-system/Box';
5
+ import { Filter } from '@strapi/icons';
6
+ import { FilterListURLQuery, FilterPopoverURLQuery } from '@strapi/helper-plugin';
7
+ import { getMessage } from '../../utils';
8
+
9
+ const TableFilters = ({ displayedFilters }) => {
10
+ const [isVisible, setIsVisible] = useState(false);
11
+ const buttonRef = useRef();
12
+
13
+ const handleToggle = () => {
14
+ setIsVisible(prev => !prev);
15
+ };
16
+
17
+ return (
18
+ <>
19
+ <Box paddingTop={1} paddingBottom={1}>
20
+ <Button
21
+ variant="tertiary"
22
+ ref={buttonRef}
23
+ startIcon={<Filter />}
24
+ onClick={handleToggle}
25
+ size="S"
26
+ >
27
+ {getMessage('page.discover.table.filters')}
28
+ </Button>
29
+ {isVisible && (
30
+ <FilterPopoverURLQuery
31
+ displayedFilters={displayedFilters}
32
+ isVisible={isVisible}
33
+ onToggle={handleToggle}
34
+ source={buttonRef}
35
+ />
36
+ )}
37
+ </Box>
38
+ <FilterListURLQuery filtersSchema={displayedFilters} />
39
+ </>
40
+ );
41
+ };
42
+
43
+ TableFilters.propTypes = {
44
+ displayedFilters: PropTypes.arrayOf(
45
+ PropTypes.shape({
46
+ name: PropTypes.string.isRequired,
47
+ metadatas: PropTypes.shape({ label: PropTypes.string }),
48
+ fieldSchema: PropTypes.shape({ type: PropTypes.string }),
49
+ })
50
+ ).isRequired,
51
+ };
52
+
53
+ export default TableFilters;
@@ -0,0 +1,35 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Box } from '@strapi/design-system/Box';
4
+ import { Flex } from '@strapi/design-system/Flex';
5
+ import { PaginationURLQuery, PageSizeURLQuery } from '@strapi/helper-plugin';
6
+
7
+ const TablePagination = ({ pagination }) => {
8
+ return (
9
+ <Box paddingTop={4}>
10
+ <Flex alignItems="flex-end" justifyContent="space-between">
11
+ <PageSizeURLQuery trackedEvent="willChangeNumberOfEntriesPerPage" />
12
+ <PaginationURLQuery pagination={pagination} />
13
+ </Flex>
14
+ </Box>
15
+ );
16
+ };
17
+
18
+ TablePagination.defaultProps = {
19
+ pagination: {
20
+ pageCount: 0,
21
+ pageSize: 10,
22
+ total: 0,
23
+ },
24
+ };
25
+
26
+ TablePagination.propTypes = {
27
+ pagination: PropTypes.shape({
28
+ page: PropTypes.number,
29
+ pageCount: PropTypes.number,
30
+ pageSize: PropTypes.number,
31
+ total: PropTypes.number,
32
+ }),
33
+ };
34
+
35
+ export default TablePagination;
@@ -0,0 +1,9 @@
1
+
2
+ import React from 'react';
3
+
4
+ const initSize = 576;
5
+
6
+ const CommentsIcon = ({ width = 24, height = 24 }) =>
7
+ <svg viewBox={`0 0 ${width} ${height}`} xmlns="http://www.w3.org/2000/svg"><g style={ {transform: `scale(${width/initSize})` } }><path d="M416 192c0-88.4-93.1-160-208-160S0 103.6 0 192c0 34.3 14.1 65.9 38 92-13.4 30.2-35.5 54.2-35.8 54.5-2.2 2.3-2.8 5.7-1.5 8.7S4.8 352 8 352c36.6 0 66.9-12.3 88.7-25 32.2 15.7 70.3 25 111.3 25 114.9 0 208-71.6 208-160zm122 220c23.9-26 38-57.7 38-92 0-66.9-53.5-124.2-129.3-148.1.9 6.6 1.3 13.3 1.3 20.1 0 105.9-107.7 192-240 192-10.8 0-21.3-.8-31.7-1.9C207.8 439.6 281.8 480 368 480c41 0 79.1-9.2 111.3-25 21.8 12.7 52.1 25 88.7 25 3.2 0 6.1-1.9 7.3-4.8 1.3-2.9.7-6.3-1.5-8.7-.3-.3-22.4-24.2-35.8-54.5z"/></g></svg>;
8
+
9
+ export default CommentsIcon;
@@ -0,0 +1,6 @@
1
+ import CommentsIcon from './comments';
2
+ import ReviewIcon from './review';
3
+ import LockIcon from './lock';
4
+ import UnlockIcon from './unlock';
5
+
6
+ export { CommentsIcon, ReviewIcon, LockIcon, UnlockIcon };
@@ -0,0 +1,22 @@
1
+
2
+ import React from 'react';
3
+
4
+ const initSize = 330;
5
+
6
+ const LockIcon = ({ width, height, size = 16 }) =>
7
+ <svg
8
+ width={width || size}
9
+ height={height || size}
10
+ viewBox={`0 0 ${width || size} ${height || size}`}
11
+ style={{ width: `${width || size}px`, height: `${height || size}px`, }}
12
+ xmlns="http://www.w3.org/2000/svg">
13
+ <g style={ { transform: `scale(${(width || size)/initSize})` } }>
14
+ <path d="M165,330c63.411,0,115-51.589,115-115c0-29.771-11.373-56.936-30-77.379V85c0-46.869-38.131-85-85-85
15
+ S80.001,38.131,80.001,85v52.619C61.373,158.064,50,185.229,50,215C50,278.411,101.589,330,165,330z M180,219.986V240
16
+ c0,8.284-6.716,15-15,15s-15-6.716-15-15v-20.014c-6.068-4.565-10-11.824-10-19.986c0-13.785,11.215-25,25-25s25,11.215,25,25
17
+ C190,208.162,186.068,215.421,180,219.986z M110.001,85c0-30.327,24.673-55,54.999-55c30.327,0,55,24.673,55,55v29.029
18
+ C203.652,105.088,184.91,100,165,100c-19.909,0-38.651,5.088-54.999,14.028V85z"/>
19
+ </g>
20
+ </svg>
21
+
22
+ export default LockIcon;
@@ -0,0 +1,18 @@
1
+
2
+ import React from 'react';
3
+
4
+ const initSize = 24;
5
+
6
+ const ReviewIcon = ({ width, height, size = 16 }) =>
7
+ <svg
8
+ width={width || size}
9
+ height={height || size}
10
+ viewBox={`0 0 ${width || size} ${height || size}`}
11
+ style={{ width: `${width || size}px`, height: `${height || size}px`, }}
12
+ xmlns="http://www.w3.org/2000/svg">
13
+ <g style={ {transform: `scale(${(width || size)/initSize})` } }>
14
+ <path strokeWidth="1" d="M5.5,21 C7.98528137,21 10,18.9852814 10,16.5 C10,14.0147186 7.98528137,12 5.5,12 C3.01471863,12 1,14.0147186 1,16.5 C1,18.9852814 3.01471863,21 5.5,21 Z M1,16 L1,7 L1,6.5 C1,4.01471863 3.01471863,2 5.5,2 L6,2 M23,16 L23,7 L23,6.5 C23,4.01471863 20.9852814,2 18.5,2 L18,2 M18.5,21 C20.9852814,21 23,18.9852814 23,16.5 C23,14.0147186 20.9852814,12 18.5,12 C16.0147186,12 14,14.0147186 14,16.5 C14,18.9852814 16.0147186,21 18.5,21 Z M10,17 C10,17 10,15 12,15 C14,15 14,17 14,17"/>
15
+ </g>
16
+ </svg>
17
+
18
+ export default ReviewIcon;
@@ -0,0 +1,20 @@
1
+
2
+ import React from 'react';
3
+
4
+ const initSize = 330;
5
+
6
+ const UnlockIcon = ({ width, height, size = 16 }) =>
7
+ <svg
8
+ width={width || size}
9
+ height={height || size}
10
+ viewBox={`0 0 ${width || size} ${height || size}`}
11
+ style={{ width: `${width || size}px`, height: `${height || size}px`, }}
12
+ xmlns="http://www.w3.org/2000/svg">
13
+ <g style={ { transform: `scale(${(width || size)/initSize})` } }>
14
+ <path d="M15,160c8.283,0,15-6.716,15-15V85c0-30.327,24.672-55,55-55c30.326,0,55,24.673,55,55v42.893
15
+ c-24.479,21.105-40,52.327-40,87.107c0,63.411,51.588,115,115,115c63.41,0,115-51.589,115-115s-51.59-115-115-115
16
+ c-15.961,0-31.172,3.271-45,9.174V85c0-46.869-38.131-85-85-85S0,38.131,0,85v60C0,153.284,6.715,160,15,160z"/>
17
+ </g>
18
+ </svg>
19
+
20
+ export default UnlockIcon;
@@ -1,49 +1,65 @@
1
+ import { prefixPluginTranslations } from '@strapi/helper-plugin';
1
2
  import pluginPkg from '../../package.json';
2
3
  import pluginId from './pluginId';
4
+ import Initializer from './components/Initializer';
5
+ import PluginIcon from './components/PluginIcon';
3
6
  import pluginPermissions from './permissions';
4
- import pluginLogo from './assets/images/logo.svg';
5
- import App from './containers/App';
6
- import Initializer from './containers/Initializer';
7
- import lifecycles from './lifecycles';
8
- import trads from './translations';
7
+ import reducers from './reducers';
9
8
 
10
- export default strapi => {
11
- const pluginDescription = pluginPkg.strapi.description || pluginPkg.description;
9
+ const name = pluginPkg.strapi.name;
12
10
 
13
- const icon = pluginPkg.strapi.icon;
14
- const name = pluginPkg.strapi.name;
15
- const plugin = {
16
- blockerComponent: null,
17
- blockerComponentProps: {},
18
- description: pluginDescription,
19
- icon,
20
- id: pluginId,
21
- initializer: Initializer,
22
- injectedComponents: [],
23
- isReady: false,
24
- isRequired: pluginPkg.strapi.required || false,
25
- layout: null,
26
- lifecycles,
27
- mainComponent: App,
28
- name,
29
- pluginLogo,
30
- preventComponentRendering: false,
31
- trads,
32
- menu: {
33
- pluginsSectionLinks: [
34
- {
35
- destination: `/plugins/${pluginId}`,
36
- icon,
37
- name,
38
- label: {
39
- id: `${pluginId}.plugin.name`,
40
- defaultMessage: 'COMMENTS',
41
- },
42
- permissions: pluginPermissions.main,
43
- },
44
- ],
45
- },
46
- };
11
+ export default {
12
+ register(app) {
13
+ app.addMenuLink({
14
+ to: `/plugins/${pluginId}/discover`,
15
+ badgeContent: 1,
16
+ icon: PluginIcon,
17
+ intlLabel: {
18
+ id: `${pluginId}.plugin.name`,
19
+ defaultMessage: name,
20
+ },
21
+ Component: async () => {
22
+ const component = await import(/* webpackChunkName: "[request]" */ './pages/App');
47
23
 
48
- return strapi.registerPlugin(plugin);
24
+ return component;
25
+ },
26
+ permissions: pluginPermissions,
27
+ });
28
+ app.addReducers(reducers);
29
+ app.registerPlugin({
30
+ id: pluginId,
31
+ initializer: Initializer,
32
+ isReady: false,
33
+ name,
34
+ });
35
+ },
36
+
37
+ bootstrap(app) {
38
+ // app.injectContentManagerComponent('editView', 'informations', {
39
+ // name: 'comments-link',
40
+ // Component: () => 'TODO: Comments count',
41
+ // });
42
+ },
43
+
44
+ async registerTrads({ locales }) {
45
+ const importedTrads = await Promise.all(
46
+ locales.map(locale => {
47
+ return import(`./translations/${locale}.json`)
48
+ .then(({ default: data }) => {
49
+ return {
50
+ data: prefixPluginTranslations(data, pluginId),
51
+ locale,
52
+ };
53
+ })
54
+ .catch(() => {
55
+ return {
56
+ data: {},
57
+ locale,
58
+ };
59
+ });
60
+ })
61
+ );
62
+
63
+ return Promise.resolve(importedTrads);
64
+ },
49
65
  };
@@ -0,0 +1,71 @@
1
+ /**
2
+ *
3
+ * This component is the skeleton around the actual pages, and should only
4
+ * contain code that should be seen on all pages. (e.g. navigation bar)
5
+ *
6
+ */
7
+
8
+ import React from 'react';
9
+ import { connect } from 'react-redux';
10
+ import { bindActionCreators, compose } from 'redux';
11
+ import { Switch, Route } from 'react-router-dom';
12
+ import { useQuery } from 'react-query';
13
+ import {
14
+ NotFound,
15
+ LoadingIndicatorPage,
16
+ useNotification } from '@strapi/helper-plugin';
17
+
18
+ import ComingSoonPage from '../ComingSoonPage';
19
+ import getUrl from '../../utils/getUrl';
20
+ import Discover from '../Discover';
21
+ import Details from '../Details';
22
+ import { fetchConfig } from './utils/api';
23
+ import { setConfig } from './reducer/actions';
24
+ import makeAppView from './reducer/selectors';
25
+
26
+ const App = ({ setConfig }) => {
27
+
28
+ const toggleNotification = useNotification();
29
+
30
+ const { isLoading, isFetching } = useQuery(
31
+ 'get-config', () => fetchConfig(toggleNotification),
32
+ {
33
+ initialData: { },
34
+ onSuccess: (response) => {
35
+ setConfig(response);
36
+ }
37
+ }
38
+ );
39
+
40
+ if (isLoading || isFetching) {
41
+ return (<LoadingIndicatorPage />)
42
+ }
43
+
44
+ return (
45
+ <div>
46
+ <Switch>
47
+ <Route path={ getUrl('dashboard') } component={ComingSoonPage} exact />
48
+ <Route path={ getUrl('discover') } component={Discover} exact />
49
+ <Route path={ getUrl('discover/:id') } component={Details} exact />
50
+ <Route path={ getUrl('reports') } component={ComingSoonPage} exact />
51
+ <Route path={ getUrl('settings') } component={ComingSoonPage} exact />
52
+ <Route component={NotFound} />
53
+ </Switch>
54
+ </div>
55
+ );
56
+ };
57
+
58
+ const mapStateToProps = makeAppView();
59
+
60
+ export function mapDispatchToProps(dispatch) {
61
+ return bindActionCreators(
62
+ { setConfig },
63
+ dispatch
64
+ );
65
+ }
66
+ const withConnect = connect(
67
+ mapStateToProps,
68
+ mapDispatchToProps
69
+ );
70
+
71
+ export default compose(withConnect)(App);
@@ -0,0 +1,8 @@
1
+ import { GET_CONFIG, SET_CONFIG } from "./constants";
2
+
3
+ export const setConfig = data => ({
4
+ data,
5
+ type: SET_CONFIG,
6
+ });
7
+
8
+ export const getConfig = () => ({ type: GET_CONFIG });
@@ -0,0 +1,4 @@
1
+ export const REDUCER_NAME = 'plugin-comments_app';
2
+
3
+ export const SET_CONFIG = 'SET_CONFIG';
4
+ export const GET_CONFIG = 'GET_CONFIG';
@@ -0,0 +1,26 @@
1
+ import produce from 'immer'; // current
2
+ import { set } from 'lodash';
3
+ import { GET_CONFIG, SET_CONFIG } from './constants';
4
+
5
+ const initialState = {
6
+ config: {},
7
+ };
8
+
9
+ const reducer = (state = initialState, action) =>
10
+ // eslint-disable-next-line consistent-return
11
+ produce(state, draftState => {
12
+ switch (action.type) {
13
+ case SET_CONFIG: {
14
+ set(draftState, 'config', action.data);
15
+ break;
16
+ }
17
+ case GET_CONFIG: {
18
+ return draftState?.config;
19
+ }
20
+ default:
21
+ return draftState;
22
+ }
23
+ });
24
+
25
+ export default reducer;
26
+ export { initialState };
@@ -0,0 +1,7 @@
1
+ const initReducer = (initialState) => {
2
+ return {
3
+ ...initialState,
4
+ };
5
+ };
6
+
7
+ export default initReducer;
@@ -0,0 +1,35 @@
1
+
2
+
3
+ import { createSelector } from 'reselect';
4
+ import { initialState } from './';
5
+ import { REDUCER_NAME } from './constants';
6
+
7
+ /**
8
+ * Direct selector to the listView state domain
9
+ */
10
+ const appView = () => state => state[REDUCER_NAME] || initialState;
11
+
12
+ /**
13
+ * Other specific selectors
14
+ */
15
+
16
+ /**
17
+ * Default selector used by listView
18
+ */
19
+
20
+ const makeAppView = () =>
21
+ createSelector(
22
+ appView(),
23
+ substate => {
24
+ return substate;
25
+ }
26
+ );
27
+
28
+ const selectConfig = state => {
29
+ const { config } = state;
30
+
31
+ return config;
32
+ };
33
+
34
+ export default makeAppView;
35
+ export { appView, selectConfig };
@@ -0,0 +1,12 @@
1
+ import { getApiURL, axiosInstance, handleAPIError } from '../../../utils';
2
+
3
+ // eslint-disable-next-line import/prefer-default-export
4
+ export const fetchConfig = async (toggleNotification) => {
5
+ try {
6
+ const { data } = await axiosInstance.get(getApiURL(`moderate/config`));
7
+
8
+ return data;
9
+ } catch (err) {
10
+ handleAPIError(err, toggleNotification);
11
+ }
12
+ };
@@ -0,0 +1,25 @@
1
+ /*
2
+ *
3
+ * Coming soon page
4
+ *
5
+ */
6
+
7
+ import React, { memo } from 'react';
8
+ import { Box } from '@strapi/design-system/Box';
9
+ import { EmptyStateLayout } from '@strapi/design-system/EmptyStateLayout';
10
+ import { Layout } from '@strapi/design-system/Layout';
11
+ import { Illo } from '@strapi/icons';
12
+ import getMessage from '../../utils/getMessage';
13
+ import Nav from '../../components/Nav';
14
+
15
+ const ComingSoonPage = () => {
16
+ return (<Box background="neutral100">
17
+ <Layout sideNav={<Nav />}>
18
+ <Box padding={8} background="neutral100">
19
+ <EmptyStateLayout icon={<Illo />} content={getMessage('page.coming.soon')} />
20
+ </Box>
21
+ </Layout>
22
+ </Box>);
23
+ }
24
+
25
+ export default memo(ComingSoonPage);