@selfcommunity/react-ui 0.7.9-alpha.8 → 0.7.9-alpha.80

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 (185) hide show
  1. package/lib/cjs/components/AccountRecover/AccountRecover.js +6 -1
  2. package/lib/cjs/components/BottomNavigation/BottomNavigation.js +4 -3
  3. package/lib/cjs/components/CategoryHeader/Skeleton.js +3 -2
  4. package/lib/cjs/components/ChangeGroupCover/ChangeGroupCover.js +6 -6
  5. package/lib/cjs/components/ChangeGroupPicture/ChangeGroupPicture.js +19 -16
  6. package/lib/cjs/components/Composer/Attributes/Attributes.js +3 -3
  7. package/lib/cjs/components/Composer/Composer.js +3 -3
  8. package/lib/cjs/components/Composer/Layer/AudienceLayer/AudienceLayer.d.ts +1 -1
  9. package/lib/cjs/components/Composer/Layer/AudienceLayer/AudienceLayer.js +9 -19
  10. package/lib/cjs/components/Editor/Editor.js +2 -0
  11. package/lib/cjs/components/Editor/nodes/ImageNode.js +6 -0
  12. package/lib/cjs/components/Editor/plugins/ImagePlugin.js +4 -0
  13. package/lib/cjs/components/Editor/plugins/ToolbarPlugin.js +17 -3
  14. package/lib/cjs/components/FeedObject/Actions/Share/Share.js +18 -16
  15. package/lib/cjs/components/FeedObject/Contributors/Contributors.js +1 -1
  16. package/lib/cjs/components/FeedObject/FeedObject.d.ts +1 -0
  17. package/lib/cjs/components/FeedObject/FeedObject.js +27 -8
  18. package/lib/cjs/components/FeedObject/Poll/Poll.js +20 -20
  19. package/lib/cjs/components/FeedUpdatesWidget/FeedUpdatesWidget.js +1 -1
  20. package/lib/cjs/components/Footer/Footer.js +1 -1
  21. package/lib/cjs/components/Group/Group.d.ts +8 -0
  22. package/lib/cjs/components/Group/Group.js +17 -5
  23. package/lib/cjs/components/GroupAutocomplete/GroupAutocomplete.js +1 -1
  24. package/lib/cjs/components/GroupForm/GroupForm.js +64 -13
  25. package/lib/cjs/components/GroupHeader/GroupHeader.d.ts +6 -5
  26. package/lib/cjs/components/GroupHeader/GroupHeader.js +53 -11
  27. package/lib/cjs/components/GroupInfoWidget/GroupInfoWidget.js +63 -9
  28. package/lib/cjs/components/GroupInviteButton/GroupInviteButton.js +31 -9
  29. package/lib/cjs/components/GroupInvitedWidget/GroupInvitedWidget.d.ts +74 -0
  30. package/lib/cjs/components/GroupInvitedWidget/GroupInvitedWidget.js +221 -0
  31. package/lib/cjs/components/GroupInvitedWidget/Skeleton.d.ts +22 -0
  32. package/lib/cjs/components/GroupInvitedWidget/Skeleton.js +38 -0
  33. package/lib/cjs/components/GroupInvitedWidget/constants.d.ts +1 -0
  34. package/lib/cjs/components/GroupInvitedWidget/constants.js +4 -0
  35. package/lib/cjs/components/GroupInvitedWidget/index.d.ts +4 -0
  36. package/lib/cjs/components/GroupInvitedWidget/index.js +8 -0
  37. package/lib/cjs/components/GroupMembersButton/GroupMembersButton.d.ts +5 -0
  38. package/lib/cjs/components/GroupMembersButton/GroupMembersButton.js +8 -3
  39. package/lib/cjs/components/GroupMembersWidget/GroupMembersWidget.js +25 -4
  40. package/lib/cjs/components/GroupRequestsWidget/GroupRequestsWidget.d.ts +11 -5
  41. package/lib/cjs/components/GroupRequestsWidget/GroupRequestsWidget.js +18 -7
  42. package/lib/cjs/components/GroupSettingsIconButton/GroupSettingsIconButton.d.ts +48 -0
  43. package/lib/cjs/components/GroupSettingsIconButton/GroupSettingsIconButton.js +151 -0
  44. package/lib/cjs/components/GroupSettingsIconButton/index.d.ts +3 -0
  45. package/lib/cjs/components/GroupSettingsIconButton/index.js +5 -0
  46. package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.d.ts +8 -3
  47. package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.js +30 -11
  48. package/lib/cjs/components/Groups/Groups.d.ts +15 -8
  49. package/lib/cjs/components/Groups/Groups.js +86 -32
  50. package/lib/cjs/components/Groups/Skeleton.d.ts +4 -0
  51. package/lib/cjs/components/Groups/Skeleton.js +2 -2
  52. package/lib/cjs/components/InlineComposerWidget/InlineComposerWidget.js +7 -0
  53. package/lib/cjs/components/NavigationSettingsIconButton/NavigationSettingsIconButton.js +4 -4
  54. package/lib/cjs/components/NavigationToolbar/NavigationToolbar.js +9 -2
  55. package/lib/cjs/components/NavigationToolbarMobile/NavigationToolbarMobile.d.ts +1 -0
  56. package/lib/cjs/components/NavigationToolbarMobile/NavigationToolbarMobile.js +9 -1
  57. package/lib/cjs/components/Notification/Group/Group.d.ts +15 -0
  58. package/lib/cjs/components/Notification/Group/Group.js +78 -0
  59. package/lib/cjs/components/Notification/Group/index.d.ts +3 -0
  60. package/lib/cjs/components/Notification/Group/index.js +5 -0
  61. package/lib/cjs/components/Notification/Notification.js +31 -1
  62. package/lib/cjs/components/Notification/PrivateMessage/PrivateMessage.js +16 -5
  63. package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.d.ts +7 -1
  64. package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.js +16 -8
  65. package/lib/cjs/components/PrivateMessageSettingsIconButton/PrivateMessageSettingsIconButton.js +1 -1
  66. package/lib/cjs/components/PrivateMessageSnippetItem/PrivateMessageSnippetItem.js +11 -6
  67. package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.d.ts +9 -4
  68. package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.js +24 -6
  69. package/lib/cjs/components/PrivateMessageThread/PrivateMessageThread.d.ts +6 -1
  70. package/lib/cjs/components/PrivateMessageThread/PrivateMessageThread.js +46 -20
  71. package/lib/cjs/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +6 -0
  72. package/lib/cjs/components/SearchAutocomplete/SearchAutocomplete.js +22 -5
  73. package/lib/cjs/components/SnippetNotifications/SnippetNotifications.js +7 -0
  74. package/lib/cjs/components/ToastNotifications/ToastNotifications.js +7 -0
  75. package/lib/cjs/components/User/User.d.ts +6 -1
  76. package/lib/cjs/components/User/User.js +5 -4
  77. package/lib/cjs/components/UserSubscribedGroupsWidget/Skeleton.d.ts +21 -0
  78. package/lib/cjs/components/UserSubscribedGroupsWidget/Skeleton.js +46 -0
  79. package/lib/cjs/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.d.ts +68 -0
  80. package/lib/cjs/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.js +183 -0
  81. package/lib/cjs/components/UserSubscribedGroupsWidget/constants.d.ts +1 -0
  82. package/lib/cjs/components/UserSubscribedGroupsWidget/constants.js +4 -0
  83. package/lib/cjs/components/UserSubscribedGroupsWidget/index.d.ts +4 -0
  84. package/lib/cjs/components/UserSubscribedGroupsWidget/index.js +8 -0
  85. package/lib/cjs/components/VoteAudienceButton/VoteAudienceButton.js +1 -1
  86. package/lib/cjs/constants/PubSub.d.ts +28 -0
  87. package/lib/cjs/constants/PubSub.js +22 -0
  88. package/lib/cjs/index.d.ts +6 -3
  89. package/lib/cjs/index.js +13 -4
  90. package/lib/cjs/types/index.d.ts +2 -1
  91. package/lib/esm/components/AccountRecover/AccountRecover.js +6 -1
  92. package/lib/esm/components/BottomNavigation/BottomNavigation.js +5 -4
  93. package/lib/esm/components/CategoryHeader/Skeleton.js +3 -2
  94. package/lib/esm/components/ChangeGroupCover/ChangeGroupCover.js +6 -6
  95. package/lib/esm/components/ChangeGroupPicture/ChangeGroupPicture.js +19 -16
  96. package/lib/esm/components/Composer/Attributes/Attributes.js +3 -3
  97. package/lib/esm/components/Composer/Composer.js +3 -3
  98. package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.d.ts +1 -1
  99. package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.js +9 -19
  100. package/lib/esm/components/Editor/Editor.js +2 -0
  101. package/lib/esm/components/Editor/nodes/ImageNode.js +6 -0
  102. package/lib/esm/components/Editor/plugins/ImagePlugin.js +4 -0
  103. package/lib/esm/components/Editor/plugins/ToolbarPlugin.js +19 -5
  104. package/lib/esm/components/FeedObject/Actions/Share/Share.js +19 -17
  105. package/lib/esm/components/FeedObject/Contributors/Contributors.js +1 -1
  106. package/lib/esm/components/FeedObject/FeedObject.d.ts +1 -0
  107. package/lib/esm/components/FeedObject/FeedObject.js +28 -9
  108. package/lib/esm/components/FeedObject/Poll/Poll.js +20 -20
  109. package/lib/esm/components/FeedUpdatesWidget/FeedUpdatesWidget.js +1 -1
  110. package/lib/esm/components/Footer/Footer.js +2 -2
  111. package/lib/esm/components/Group/Group.d.ts +8 -0
  112. package/lib/esm/components/Group/Group.js +21 -9
  113. package/lib/esm/components/GroupAutocomplete/GroupAutocomplete.js +1 -1
  114. package/lib/esm/components/GroupForm/GroupForm.js +64 -13
  115. package/lib/esm/components/GroupHeader/GroupHeader.d.ts +6 -5
  116. package/lib/esm/components/GroupHeader/GroupHeader.js +55 -13
  117. package/lib/esm/components/GroupInfoWidget/GroupInfoWidget.js +63 -9
  118. package/lib/esm/components/GroupInviteButton/GroupInviteButton.js +31 -9
  119. package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.d.ts +74 -0
  120. package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.js +218 -0
  121. package/lib/esm/components/GroupInvitedWidget/Skeleton.d.ts +22 -0
  122. package/lib/esm/components/GroupInvitedWidget/Skeleton.js +34 -0
  123. package/lib/esm/components/GroupInvitedWidget/constants.d.ts +1 -0
  124. package/lib/esm/components/GroupInvitedWidget/constants.js +1 -0
  125. package/lib/esm/components/GroupInvitedWidget/index.d.ts +4 -0
  126. package/lib/esm/components/GroupInvitedWidget/index.js +4 -0
  127. package/lib/esm/components/GroupMembersButton/GroupMembersButton.d.ts +5 -0
  128. package/lib/esm/components/GroupMembersButton/GroupMembersButton.js +9 -4
  129. package/lib/esm/components/GroupMembersWidget/GroupMembersWidget.js +26 -5
  130. package/lib/esm/components/GroupRequestsWidget/GroupRequestsWidget.d.ts +11 -5
  131. package/lib/esm/components/GroupRequestsWidget/GroupRequestsWidget.js +18 -7
  132. package/lib/esm/components/GroupSettingsIconButton/GroupSettingsIconButton.d.ts +48 -0
  133. package/lib/esm/components/GroupSettingsIconButton/GroupSettingsIconButton.js +148 -0
  134. package/lib/esm/components/GroupSettingsIconButton/index.d.ts +3 -0
  135. package/lib/esm/components/GroupSettingsIconButton/index.js +2 -0
  136. package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.d.ts +8 -3
  137. package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.js +30 -11
  138. package/lib/esm/components/Groups/Groups.d.ts +15 -8
  139. package/lib/esm/components/Groups/Groups.js +91 -37
  140. package/lib/esm/components/Groups/Skeleton.d.ts +4 -0
  141. package/lib/esm/components/Groups/Skeleton.js +2 -2
  142. package/lib/esm/components/InlineComposerWidget/InlineComposerWidget.js +9 -2
  143. package/lib/esm/components/NavigationSettingsIconButton/NavigationSettingsIconButton.js +4 -4
  144. package/lib/esm/components/NavigationToolbar/NavigationToolbar.js +10 -3
  145. package/lib/esm/components/NavigationToolbarMobile/NavigationToolbarMobile.d.ts +1 -0
  146. package/lib/esm/components/NavigationToolbarMobile/NavigationToolbarMobile.js +11 -3
  147. package/lib/esm/components/Notification/Group/Group.d.ts +15 -0
  148. package/lib/esm/components/Notification/Group/Group.js +75 -0
  149. package/lib/esm/components/Notification/Group/index.d.ts +3 -0
  150. package/lib/esm/components/Notification/Group/index.js +2 -0
  151. package/lib/esm/components/Notification/Notification.js +31 -1
  152. package/lib/esm/components/Notification/PrivateMessage/PrivateMessage.js +16 -5
  153. package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.d.ts +7 -1
  154. package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.js +17 -9
  155. package/lib/esm/components/PrivateMessageSettingsIconButton/PrivateMessageSettingsIconButton.js +1 -1
  156. package/lib/esm/components/PrivateMessageSnippetItem/PrivateMessageSnippetItem.js +11 -6
  157. package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.d.ts +9 -4
  158. package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.js +26 -8
  159. package/lib/esm/components/PrivateMessageThread/PrivateMessageThread.d.ts +6 -1
  160. package/lib/esm/components/PrivateMessageThread/PrivateMessageThread.js +48 -22
  161. package/lib/esm/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +7 -1
  162. package/lib/esm/components/SearchAutocomplete/SearchAutocomplete.js +22 -5
  163. package/lib/esm/components/SnippetNotifications/SnippetNotifications.js +7 -0
  164. package/lib/esm/components/ToastNotifications/ToastNotifications.js +7 -0
  165. package/lib/esm/components/User/User.d.ts +6 -1
  166. package/lib/esm/components/User/User.js +5 -4
  167. package/lib/esm/components/UserSubscribedGroupsWidget/Skeleton.d.ts +21 -0
  168. package/lib/esm/components/UserSubscribedGroupsWidget/Skeleton.js +42 -0
  169. package/lib/esm/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.d.ts +68 -0
  170. package/lib/esm/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.js +180 -0
  171. package/lib/esm/components/UserSubscribedGroupsWidget/constants.d.ts +1 -0
  172. package/lib/esm/components/UserSubscribedGroupsWidget/constants.js +1 -0
  173. package/lib/esm/components/UserSubscribedGroupsWidget/index.d.ts +4 -0
  174. package/lib/esm/components/UserSubscribedGroupsWidget/index.js +4 -0
  175. package/lib/esm/components/VoteAudienceButton/VoteAudienceButton.js +1 -1
  176. package/lib/esm/constants/PubSub.d.ts +28 -0
  177. package/lib/esm/constants/PubSub.js +19 -0
  178. package/lib/esm/index.d.ts +6 -3
  179. package/lib/esm/index.js +6 -3
  180. package/lib/esm/types/index.d.ts +2 -1
  181. package/lib/umd/311.js +2 -0
  182. package/lib/umd/react-ui.js +1 -1
  183. package/package.json +9 -9
  184. package/lib/umd/871.js +0 -2
  185. /package/lib/umd/{871.js.LICENSE.txt → 311.js.LICENSE.txt} +0 -0
@@ -0,0 +1,148 @@
1
+ import { __rest } from "tslib";
2
+ import React, { useState } from 'react';
3
+ import { styled } from '@mui/material/styles';
4
+ import { SwipeableDrawer, MenuItem, IconButton, Menu, useTheme, useMediaQuery, List, ListItem } from '@mui/material';
5
+ import { FormattedMessage } from 'react-intl';
6
+ import Icon from '@mui/material/Icon';
7
+ import classNames from 'classnames';
8
+ import { useThemeProps } from '@mui/system';
9
+ import { Link, SCRoutes, useSCRouting, useSCUser } from '@selfcommunity/react-core';
10
+ import ConfirmDialog from '../../shared/ConfirmDialog/ConfirmDialog';
11
+ import { GroupService } from '@selfcommunity/api-services';
12
+ import { SCEventType, SCTopicType } from '../../constants/PubSub';
13
+ import PubSub from 'pubsub-js';
14
+ const PREFIX = 'SCGroupSettingsIconButton';
15
+ const classes = {
16
+ root: `${PREFIX}-root`,
17
+ drawerRoot: `${PREFIX}-drawer-root`,
18
+ menuRoot: `${PREFIX}-menu-root`,
19
+ paper: `${PREFIX}-paper`,
20
+ item: `${PREFIX}-item`
21
+ };
22
+ const Root = styled(IconButton, {
23
+ name: PREFIX,
24
+ slot: 'Root'
25
+ })(() => ({}));
26
+ const SwipeableDrawerRoot = styled(SwipeableDrawer, {
27
+ name: PREFIX,
28
+ slot: 'DrawerRoot'
29
+ })(() => ({}));
30
+ const MenuRoot = styled(Menu, {
31
+ name: PREFIX,
32
+ slot: 'MenuRoot'
33
+ })(() => ({}));
34
+ /**
35
+ * > API documentation for the Community-JS PrivateMessageSettingsIconButton component. Learn about the available props and the CSS API.
36
+
37
+ #### Import
38
+
39
+ ```jsx
40
+ import {PrivateMessageSettingsIconButton} from '@selfcommunity/react-ui';
41
+ ```
42
+
43
+ #### Component Name
44
+
45
+ The name `SCGroupSettingsIconButton` can be used when providing style overrides in the theme.
46
+
47
+
48
+ #### CSS
49
+
50
+ |Rule Name|Global class|Description|
51
+ |---|---|---|
52
+ |root|.SCGroupSettingsIconButton-root|Styles applied to the root element.|
53
+
54
+ * @param inProps
55
+ */
56
+ export default function GroupSettingsIconButton(inProps) {
57
+ // PROPS
58
+ const props = useThemeProps({
59
+ props: inProps,
60
+ name: PREFIX
61
+ });
62
+ const { className = null, group, user, onRemoveSuccess } = props, rest = __rest(props, ["className", "group", "user", "onRemoveSuccess"]);
63
+ // STATE
64
+ const [anchorEl, setAnchorEl] = useState(null);
65
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
66
+ // HOOKS
67
+ const theme = useTheme();
68
+ const isMobile = useMediaQuery(theme.breakpoints.down('md'));
69
+ const scRoutingContext = useSCRouting();
70
+ // CONTEXT
71
+ const scUserContext = useSCUser();
72
+ // HANDLERS
73
+ const handleOpen = (event) => {
74
+ setAnchorEl(event.currentTarget);
75
+ };
76
+ const handleClose = () => {
77
+ setAnchorEl(null);
78
+ };
79
+ const handleOpenDialog = () => {
80
+ setOpenConfirmDialog(true);
81
+ setAnchorEl(null);
82
+ };
83
+ const handleCloseDialog = () => {
84
+ setOpenConfirmDialog(false);
85
+ setAnchorEl(null);
86
+ };
87
+ /**
88
+ * Notify UI when a user is removed from a group
89
+ * @param group
90
+ * @param user
91
+ */
92
+ function notifyChanges(group, user) {
93
+ if (group && user) {
94
+ PubSub.publish(`${SCTopicType.GROUP}.${SCEventType.REMOVE_MEMBER}`, { group, user });
95
+ }
96
+ }
97
+ /**
98
+ * Handles thread deletion
99
+ */
100
+ function handleRemoveUser() {
101
+ GroupService.removeUserFromGroup(group.id, user.id)
102
+ .then(() => {
103
+ notifyChanges(group, user);
104
+ onRemoveSuccess && onRemoveSuccess();
105
+ handleCloseDialog();
106
+ })
107
+ .catch((error) => {
108
+ setOpenConfirmDialog(false);
109
+ console.log(error);
110
+ });
111
+ }
112
+ if (scUserContext.user.id === user.id) {
113
+ return null;
114
+ }
115
+ /**
116
+ *
117
+ */
118
+ const renderList = () => {
119
+ if (isMobile) {
120
+ return [
121
+ React.createElement(ListItem, { className: classes.item, key: "message", component: Link, to: scRoutingContext.url(SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user) },
122
+ React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" })),
123
+ React.createElement(ListItem, { className: classes.item, key: "delete", onClick: handleOpenDialog },
124
+ React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.remove", defaultMessage: "ui.groupSettingsIconButton.item.remove" }))
125
+ ];
126
+ }
127
+ else {
128
+ return [
129
+ React.createElement(MenuItem, { className: classes.item, component: Link, to: scRoutingContext.url(SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user), key: "message" },
130
+ React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" })),
131
+ React.createElement(MenuItem, { className: classes.item, onClick: handleOpenDialog, key: "delete" },
132
+ React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.remove", defaultMessage: "ui.groupSettingsIconButton.item.remove" }))
133
+ ];
134
+ }
135
+ };
136
+ return (React.createElement(React.Fragment, null,
137
+ React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { onClick: handleOpen }),
138
+ React.createElement(Icon, null, "more_vert")),
139
+ isMobile ? (React.createElement(SwipeableDrawerRoot, { className: classes.drawerRoot, anchor: "bottom", open: Boolean(anchorEl), onClose: handleClose, onOpen: handleOpen, PaperProps: { className: classes.paper }, disableSwipeToOpen: true },
140
+ React.createElement(List, null, renderList()))) : (React.createElement(MenuRoot, { className: classes.menuRoot, anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, PaperProps: { className: classes.paper } }, renderList())),
141
+ openConfirmDialog && (React.createElement(ConfirmDialog, { open: openConfirmDialog, title: React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.dialog.msg", defaultMessage: "ui.groupSettingsIconButton.dialog.msg", values: {
142
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
143
+ // @ts-ignore
144
+ b: (...chunks) => React.createElement("strong", null, chunks),
145
+ user: user.username,
146
+ group: group.name
147
+ } }), btnConfirm: React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.dialog.confirm", defaultMessage: "ui.groupSettingsIconButton.dialog.confirm" }), onConfirm: handleRemoveUser, onClose: handleCloseDialog }))));
148
+ }
@@ -0,0 +1,3 @@
1
+ import GroupSettingsIconButton, { GroupSettingsIconButtonProps } from './GroupSettingsIconButton';
2
+ export default GroupSettingsIconButton;
3
+ export { GroupSettingsIconButtonProps };
@@ -0,0 +1,2 @@
1
+ import GroupSettingsIconButton from './GroupSettingsIconButton';
2
+ export default GroupSettingsIconButton;
@@ -1,4 +1,4 @@
1
- import { SCGroupType } from '@selfcommunity/types';
1
+ import { SCGroupType, SCUserType } from '@selfcommunity/types';
2
2
  export interface GroupSubscribeButtonProps {
3
3
  /**
4
4
  * Overrides or extends the styles applied to the component.
@@ -16,11 +16,16 @@ export interface GroupSubscribeButtonProps {
16
16
  */
17
17
  groupId?: number;
18
18
  /**
19
- * onJoin callback
19
+ * The user to be accepted into the group
20
+ * @default null
21
+ */
22
+ user?: SCUserType;
23
+ /**
24
+ * onSubscribe callback
20
25
  * @param user
21
26
  * @param joined
22
27
  */
23
- onJoin?: (group: SCGroupType, member: boolean) => any;
28
+ onSubscribe?: (group: SCGroupType, status: string | null) => any;
24
29
  /**
25
30
  * Others properties
26
31
  */
@@ -9,6 +9,8 @@ import { FormattedMessage } from 'react-intl';
9
9
  import classNames from 'classnames';
10
10
  import { useThemeProps } from '@mui/system';
11
11
  import { SCOPE_SC_UI } from '../../constants/Errors';
12
+ import { SCEventType, SCTopicType } from '../../constants/PubSub';
13
+ import PubSub from 'pubsub-js';
12
14
  const PREFIX = 'SCGroupSubscribeButton';
13
15
  const classes = {
14
16
  root: `${PREFIX}-root`
@@ -47,7 +49,7 @@ export default function GroupSubscribeButton(inProps) {
47
49
  props: inProps,
48
50
  name: PREFIX
49
51
  });
50
- const { className, groupId, group, onJoin } = props, rest = __rest(props, ["className", "groupId", "group", "onJoin"]);
52
+ const { className, groupId, group, user, onSubscribe } = props, rest = __rest(props, ["className", "groupId", "group", "user", "onSubscribe"]);
51
53
  // STATE
52
54
  const [status, setStatus] = useState(null);
53
55
  // CONTEXT
@@ -61,7 +63,7 @@ export default function GroupSubscribeButton(inProps) {
61
63
  group,
62
64
  cacheStrategy: authUserId ? CacheStrategies.CACHE_FIRST : CacheStrategies.STALE_WHILE_REVALIDATE
63
65
  });
64
- const canEdit = useMemo(() => { var _a; return scUserContext.user && ((_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id) === scUserContext.user.id; }, [scUserContext.user, (_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id]);
66
+ const isGroupAdmin = useMemo(() => { var _a; return scUserContext.user && ((_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id) === scUserContext.user.id; }, [scUserContext.user, (_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id]);
65
67
  useEffect(() => {
66
68
  /**
67
69
  * Call scGroupsManager.subscriptionStatus inside an effect
@@ -71,11 +73,25 @@ export default function GroupSubscribeButton(inProps) {
71
73
  setStatus(scGroupsManager.subscriptionStatus(scGroup));
72
74
  }
73
75
  }, [authUserId, scGroupsManager.subscriptionStatus]);
74
- const subscribe = () => {
76
+ /**
77
+ * Notify UI when a member is added to a group
78
+ * @param group
79
+ * @param user
80
+ */
81
+ function notifyChanges(group, user) {
82
+ if (group && user) {
83
+ PubSub.publish(`${SCTopicType.GROUP}.${SCEventType.ADD_MEMBER}`, { group, user });
84
+ }
85
+ }
86
+ const subscribe = (user) => {
75
87
  scGroupsManager
76
- .subscribe(scGroup)
88
+ .subscribe(scGroup, user === null || user === void 0 ? void 0 : user.id)
77
89
  .then(() => {
78
- // onJoin && onJoin(scGroup, !joined);
90
+ const _status = scGroup.privacy === SCGroupPrivacyType.PRIVATE && scGroup.subscription_status !== SCGroupSubscriptionStatusType.INVITED
91
+ ? SCGroupSubscriptionStatusType.REQUESTED
92
+ : SCGroupSubscriptionStatusType.SUBSCRIBED;
93
+ notifyChanges(scGroup, user);
94
+ onSubscribe && onSubscribe(scGroup, _status);
79
95
  })
80
96
  .catch((e) => {
81
97
  Logger.error(SCOPE_SC_UI, e);
@@ -85,7 +101,7 @@ export default function GroupSubscribeButton(inProps) {
85
101
  scGroupsManager
86
102
  .unsubscribe(scGroup)
87
103
  .then(() => {
88
- // onJoin && onJoin(scGroup, !joined);
104
+ onSubscribe && onSubscribe(scGroup, null);
89
105
  })
90
106
  .catch((e) => {
91
107
  Logger.error(SCOPE_SC_UI, e);
@@ -96,7 +112,7 @@ export default function GroupSubscribeButton(inProps) {
96
112
  scContext.settings.handleAnonymousAction();
97
113
  }
98
114
  else {
99
- SCGroupSubscriptionStatusType.SUBSCRIBED ? unsubscribe() : subscribe();
115
+ status === SCGroupSubscriptionStatusType.SUBSCRIBED && !(user === null || user === void 0 ? void 0 : user.id) ? unsubscribe() : (user === null || user === void 0 ? void 0 : user.id) ? subscribe(user) : subscribe();
100
116
  }
101
117
  };
102
118
  /**
@@ -106,21 +122,24 @@ export default function GroupSubscribeButton(inProps) {
106
122
  let _status;
107
123
  switch (status) {
108
124
  case SCGroupSubscriptionStatusType.REQUESTED:
109
- _status = React.createElement(FormattedMessage, { defaultMessage: "ui.groupJoinButton.waitingApproval", id: "ui.groupJoinButton.waitingApproval" });
125
+ _status = React.createElement(FormattedMessage, { defaultMessage: "ui.groupSubscribeButton.waitingApproval", id: "ui.groupSubscribeButton.waitingApproval" });
110
126
  break;
111
127
  case SCGroupSubscriptionStatusType.SUBSCRIBED:
112
128
  _status = React.createElement(FormattedMessage, { defaultMessage: "ui.groupSubscribeButton.exit", id: "ui.groupSubscribeButton.exit" });
113
129
  break;
130
+ case SCGroupSubscriptionStatusType.INVITED:
131
+ _status = React.createElement(FormattedMessage, { defaultMessage: "ui.groupSubscribeButton.accept", id: "ui.groupSubscribeButton.accept" });
132
+ break;
114
133
  default:
115
134
  scGroup.privacy === SCGroupPrivacyType.PUBLIC
116
135
  ? (_status = React.createElement(FormattedMessage, { defaultMessage: "ui.groupSubscribeButton.enter", id: "ui.groupSubscribeButton.enter" }))
117
- : (_status = React.createElement(FormattedMessage, { defaultMessage: "ui.groupJoinButton.requestAccess", id: "ui.groupJoinButton.requestAccess" }));
136
+ : (_status = React.createElement(FormattedMessage, { defaultMessage: "ui.groupSubscribeButton.requestAccess", id: "ui.groupSubscribeButton.requestAccess" }));
118
137
  break;
119
138
  }
120
139
  return _status;
121
140
  };
122
- if (!scGroup || (scGroup && !scGroup.subscription_status) || canEdit) {
141
+ if (!scGroup || (isGroupAdmin && (user === null || user === void 0 ? void 0 : user.id) === scUserContext.user.id) || (isGroupAdmin && !(user === null || user === void 0 ? void 0 : user.id))) {
123
142
  return null;
124
143
  }
125
- return (React.createElement(Root, Object.assign({ size: "small", variant: "outlined", onClick: handleSubscribeAction, loading: scUserContext.user ? scGroupsManager.isLoading(scGroup) : null, className: classNames(classes.root, className) }, rest), getStatus()));
144
+ return (React.createElement(Root, Object.assign({ size: "small", variant: "outlined", onClick: handleSubscribeAction, loading: scUserContext.user ? scGroupsManager.isLoading(scGroup) : null, disabled: status === SCGroupSubscriptionStatusType.REQUESTED, className: classNames(classes.root, className) }, rest), isGroupAdmin ? React.createElement(FormattedMessage, { defaultMessage: "ui.groupSubscribeButton.accept", id: "ui.groupSubscribeButton.accept" }) : getStatus()));
126
145
  }
@@ -1,5 +1,3 @@
1
- import { SCGroupType } from '@selfcommunity/types';
2
- import { EndpointType } from '@selfcommunity/api-services';
3
1
  import { GroupProps } from '../Group';
4
2
  export interface GroupsProps {
5
3
  /**
@@ -8,20 +6,29 @@ export interface GroupsProps {
8
6
  */
9
7
  className?: string;
10
8
  /**
11
- * Endpoint to call
9
+ * Feed API Query Params
10
+ * @default [{'limit': 20, 'offset': 0}]
12
11
  */
13
- endpoint: EndpointType;
12
+ endpointQueryParams?: Record<string, string | number>;
14
13
  /**
15
14
  * Props to spread to single group object
16
15
  * @default {variant: 'outlined', ButtonBaseProps: {disableRipple: 'true'}}
17
16
  */
18
17
  GroupComponentProps?: GroupProps;
18
+ /** If true, it means that the endpoint fetches all groups available
19
+ * @default true
20
+ */
21
+ general?: boolean;
19
22
  /**
20
- * Prefetch groups. Useful for SSR.
21
- * Use this to init the component with groups
22
- * @default null
23
+ * Show/Hide filters
24
+ * @default false
25
+ */
26
+ showFilters?: boolean;
27
+ /**
28
+ * Filters component
29
+ * @param props
23
30
  */
24
- prefetchedGroups?: SCGroupType[];
31
+ filters?: JSX.Element;
25
32
  /**
26
33
  * Other props
27
34
  */
@@ -1,10 +1,10 @@
1
- import { __awaiter, __rest } from "tslib";
1
+ import { __rest } from "tslib";
2
2
  import React, { useEffect, useMemo, useState } from 'react';
3
3
  import { styled } from '@mui/material/styles';
4
- import { Box, Grid, Typography } from '@mui/material';
5
- import { http } from '@selfcommunity/api-services';
6
- import { Logger } from '@selfcommunity/utils';
7
- import { SCPreferences, useIsComponentMountedRef, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
4
+ import { Box, Button, Grid, TextField, Typography, useMediaQuery, useTheme } from '@mui/material';
5
+ import { Endpoints, GroupService, http } from '@selfcommunity/api-services';
6
+ import { Logger, sortByAttr } from '@selfcommunity/utils';
7
+ import { SCPreferences, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
8
8
  import Skeleton from './Skeleton';
9
9
  import { FormattedMessage } from 'react-intl';
10
10
  import classNames from 'classnames';
@@ -12,9 +12,12 @@ import { SCOPE_SC_UI } from '../../constants/Errors';
12
12
  import { useThemeProps } from '@mui/system';
13
13
  import HiddenPlaceholder from '../../shared/HiddenPlaceholder';
14
14
  import { PREFIX } from './constants';
15
- import Group from '../Group';
15
+ import Group, { GroupSkeleton } from '../Group';
16
+ import { DEFAULT_PAGINATION_OFFSET } from '../../constants/Pagination';
17
+ import InfiniteScroll from '../../shared/InfiniteScroll';
16
18
  const classes = {
17
19
  root: `${PREFIX}-root`,
20
+ filters: `${PREFIX}-filter`,
18
21
  groups: `${PREFIX}-groups`,
19
22
  item: `${PREFIX}-item`,
20
23
  noResults: `${PREFIX}-no-results`,
@@ -62,10 +65,14 @@ export default function Groups(inProps) {
62
65
  props: inProps,
63
66
  name: PREFIX
64
67
  });
65
- const { endpoint, className, GroupComponentProps = { variant: 'outlined', ButtonBaseProps: { disableRipple: true, component: Box } }, prefetchedGroups = [] } = props, rest = __rest(props, ["endpoint", "className", "GroupComponentProps", "prefetchedGroups"]);
68
+ const { endpointQueryParams = { limit: 20, offset: DEFAULT_PAGINATION_OFFSET }, className, GroupComponentProps = { variant: 'outlined', ButtonBaseProps: { disableRipple: true, component: Box } }, showFilters = false, filters, general = true } = props, rest = __rest(props, ["endpointQueryParams", "className", "GroupComponentProps", "showFilters", "filters", "general"]);
66
69
  // STATE
67
70
  const [groups, setGroups] = useState([]);
68
71
  const [loading, setLoading] = useState(true);
72
+ const [next, setNext] = useState(null);
73
+ const [search, setSearch] = useState('');
74
+ const theme = useTheme();
75
+ const isMobile = useMediaQuery(theme.breakpoints.down('md'));
69
76
  // CONTEXT
70
77
  const scUserContext = useSCUser();
71
78
  const scPreferencesContext = useSCPreferences();
@@ -74,19 +81,31 @@ export default function Groups(inProps) {
74
81
  scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY].value, [scPreferencesContext.preferences]);
75
82
  // CONST
76
83
  const authUserId = scUserContext.user ? scUserContext.user.id : null;
77
- // REFS
78
- const isMountedRef = useIsComponentMountedRef();
84
+ // HANDLERS
85
+ const handleScrollUp = () => {
86
+ window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
87
+ };
79
88
  /**
80
89
  * Fetches groups list
81
90
  */
82
- const fetchGroups = (next = endpoint.url({})) => __awaiter(this, void 0, void 0, function* () {
83
- const response = yield http.request({
84
- url: next,
85
- method: endpoint.method
91
+ const fetchGroups = () => {
92
+ let groupService;
93
+ if (general) {
94
+ groupService = GroupService.searchGroups(Object.assign(Object.assign({}, endpointQueryParams), (search !== '' && { search: search })));
95
+ }
96
+ else {
97
+ groupService = GroupService.getUserGroups(Object.assign(Object.assign({}, endpointQueryParams), (search !== '' && { search: search })));
98
+ }
99
+ groupService
100
+ .then((res) => {
101
+ setGroups(res.results);
102
+ setNext(res.next);
103
+ setLoading(false);
104
+ })
105
+ .catch((error) => {
106
+ Logger.error(SCOPE_SC_UI, error);
86
107
  });
87
- const data = response.data;
88
- return data.next ? data.results.concat(yield fetchGroups(data.next)) : data.results;
89
- });
108
+ };
90
109
  /**
91
110
  * On mount, fetches groups list
92
111
  */
@@ -94,32 +113,67 @@ export default function Groups(inProps) {
94
113
  if (!contentAvailability && !authUserId) {
95
114
  return;
96
115
  }
97
- else if (prefetchedGroups.length) {
98
- setGroups(prefetchedGroups);
99
- setLoading(false);
100
- }
101
116
  else {
102
- fetchGroups()
103
- .then((data) => {
104
- if (isMountedRef.current) {
105
- setGroups(data);
106
- setLoading(false);
107
- }
108
- })
109
- .catch((error) => {
110
- Logger.error(SCOPE_SC_UI, error);
111
- });
117
+ fetchGroups();
118
+ }
119
+ }, [contentAvailability, authUserId, search]);
120
+ const handleNext = useMemo(() => () => {
121
+ if (!next) {
122
+ return;
112
123
  }
113
- }, [contentAvailability, authUserId, prefetchedGroups.length]);
124
+ return http
125
+ .request({
126
+ url: next,
127
+ method: general ? Endpoints.SearchGroups.method : Endpoints.GetUserGroups.method
128
+ })
129
+ .then((res) => {
130
+ setGroups([...groups, ...res.data.results]);
131
+ setNext(res.data.next);
132
+ })
133
+ .catch((error) => console.log(error))
134
+ .then(() => setLoading(false));
135
+ }, [next]);
136
+ /**
137
+ * Get groups filtered
138
+ */
139
+ const getFilteredGroups = () => {
140
+ if (search) {
141
+ return groups.filter((g) => g.name.toLowerCase().includes(search.toLowerCase()));
142
+ }
143
+ return groups;
144
+ };
145
+ /**
146
+ * Handle change filter name
147
+ * @param event
148
+ */
149
+ const handleOnChangeFilterName = (event) => {
150
+ setSearch(event.target.value);
151
+ };
152
+ /**
153
+ * Renders groups list
154
+ */
155
+ const filteredGroups = sortByAttr(getFilteredGroups(), 'order');
156
+ const content = (React.createElement(React.Fragment, null,
157
+ showFilters && (React.createElement(Grid, { container: true, direction: "row", justifyContent: "center", alignItems: "center", className: classes.filters }, filters ? (filters) : (React.createElement(Grid, { item: true, xs: 12, md: 6 },
158
+ React.createElement(TextField, { fullWidth: true, value: search, label: React.createElement(FormattedMessage, { id: "ui.groups.filterByName", defaultMessage: "ui.groups.filterByName" }), variant: "outlined", onChange: handleOnChangeFilterName, disabled: loading }))))),
159
+ React.createElement(React.Fragment, null, !groups.length ? (React.createElement(Box, { className: classes.noResults },
160
+ React.createElement(Typography, { variant: "h4" },
161
+ React.createElement(FormattedMessage, { id: "ui.groups.noGroups.title", defaultMessage: "ui.groups.noGroups.title" })),
162
+ React.createElement(Typography, { variant: "body1" },
163
+ React.createElement(FormattedMessage, { id: "ui.groups.noGroups.subtitle", defaultMessage: "ui.groups.noGroups.subtitle" })))) : (React.createElement(InfiniteScroll, { dataLength: groups.length, next: handleNext, hasMoreNext: Boolean(next), loaderNext: isMobile ? React.createElement(GroupSkeleton, null) : React.createElement(Skeleton, { groupsNumber: 2 }), endMessage: React.createElement(Typography, { component: "div", className: classes.endMessage },
164
+ React.createElement(FormattedMessage, { id: "ui.groups.endMessage", defaultMessage: "ui.groups.endMessage", values: {
165
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
166
+ // @ts-ignore
167
+ button: (chunk) => (React.createElement(Button, { color: "secondary", variant: "text", onClick: handleScrollUp }, chunk))
168
+ } })) },
169
+ React.createElement(Grid, { container: true, spacing: { xs: 2 }, className: classes.groups }, filteredGroups.map((group) => (React.createElement(Grid, { item: true, xs: 12, sm: 8, md: 6, key: group.id, className: classes.item },
170
+ React.createElement(Group, Object.assign({ group: group, groupId: group.id, actionRedirect: true }, GroupComponentProps)))))))))));
114
171
  // RENDER
115
172
  if (!contentAvailability && !scUserContext.user) {
116
173
  return React.createElement(HiddenPlaceholder, null);
117
174
  }
118
- const content = (React.createElement(React.Fragment, null, loading ? (React.createElement(Skeleton, null)) : (React.createElement(Grid, { container: true, spacing: { xs: 3 }, className: classes.groups }, !groups.length ? (React.createElement(Box, { className: classes.noResults },
119
- React.createElement(Typography, { variant: "h4" },
120
- React.createElement(FormattedMessage, { id: "ui.groups.noGroups.title", defaultMessage: "ui.groups.noGroups.title" })),
121
- React.createElement(Typography, { variant: "body1" },
122
- React.createElement(FormattedMessage, { id: "ui.groups.noGroups.subtitle", defaultMessage: "ui.groups.noGroups.subtitle" })))) : (React.createElement(React.Fragment, null, groups.map((group) => (React.createElement(Grid, { item: true, xs: 12, sm: 8, md: 6, key: group.id, className: classes.item },
123
- React.createElement(Group, Object.assign({ group: group, groupId: group.id }, GroupComponentProps)))))))))));
175
+ if (loading) {
176
+ return React.createElement(Skeleton, null);
177
+ }
124
178
  return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest), content));
125
179
  }
@@ -9,6 +9,10 @@ export interface GroupsSkeletonProps {
9
9
  * @default null
10
10
  */
11
11
  GroupSkeletonProps?: any;
12
+ /**
13
+ * @default 20
14
+ */
15
+ groupsNumber?: number;
12
16
  }
13
17
  /**
14
18
  * > API documentation for the Community-JS Groups Skeleton component. Learn about the available props and the CSS API.
@@ -35,8 +35,8 @@ const Root = styled(Box, {
35
35
  *
36
36
  */
37
37
  export default function GroupsSkeleton(inProps) {
38
- const { className, GroupSkeletonProps = {} } = inProps, rest = __rest(inProps, ["className", "GroupSkeletonProps"]);
38
+ const { className, GroupSkeletonProps = {}, groupsNumber = 20 } = inProps, rest = __rest(inProps, ["className", "GroupSkeletonProps", "groupsNumber"]);
39
39
  return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest),
40
- React.createElement(Grid, { container: true, spacing: { xs: 3 }, className: classes.groups }, [...Array(15)].map((category, index) => (React.createElement(Grid, { item: true, xs: 12, sm: 8, md: 6, key: index },
40
+ React.createElement(Grid, { container: true, spacing: { xs: 3 }, className: classes.groups }, [...Array(groupsNumber)].map((category, index) => (React.createElement(Grid, { item: true, xs: 12, sm: 8, md: 6, key: index },
41
41
  React.createElement(GroupSkeleton, Object.assign({ elevation: 0, variant: 'outlined' }, GroupSkeletonProps))))))));
42
42
  }
@@ -1,6 +1,6 @@
1
1
  import { __rest } from "tslib";
2
- import React, { useCallback, useState } from 'react';
3
- import { Link, SCRoutes, UserUtils, useSCContext, useSCRouting, useSCUser } from '@selfcommunity/react-core';
2
+ import React, { useCallback, useMemo, useState } from 'react';
3
+ import { Link, SCPreferences, SCRoutes, UserUtils, useSCContext, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
4
4
  import { Avatar, Box, Button, CardContent } from '@mui/material';
5
5
  import { styled } from '@mui/material/styles';
6
6
  import { FormattedMessage } from 'react-intl';
@@ -10,6 +10,7 @@ import { useThemeProps } from '@mui/system';
10
10
  import Composer from '../Composer';
11
11
  import { File, Link as MediaLink } from '../../shared/Media';
12
12
  import { PREFIX } from './constants';
13
+ import HiddenPlaceholder from '../../shared/HiddenPlaceholder';
13
14
  const classes = {
14
15
  root: `${PREFIX}-root`,
15
16
  content: `${PREFIX}-content`,
@@ -58,6 +59,9 @@ export default function InlineComposerWidget(inProps) {
58
59
  const scUserContext = useSCUser();
59
60
  const scRoutingContext = useSCRouting();
60
61
  const { enqueueSnackbar } = useSnackbar();
62
+ // PREFERENCES
63
+ const preferences = useSCPreferences();
64
+ const onlyStaffEnabled = useMemo(() => preferences.preferences[SCPreferences.CONFIGURATIONS_POST_ONLY_STAFF_ENABLED].value, [preferences.preferences]);
61
65
  // State variables
62
66
  const [open, setOpen] = useState(false);
63
67
  // Handlers
@@ -92,6 +96,9 @@ export default function InlineComposerWidget(inProps) {
92
96
  }
93
97
  setOpen(false);
94
98
  };
99
+ if (!UserUtils.isStaff(scUserContext.user) && onlyStaffEnabled) {
100
+ return React.createElement(HiddenPlaceholder, null);
101
+ }
95
102
  return (React.createElement(React.Fragment, null,
96
103
  React.createElement(Root, Object.assign({ className: classes.root }, rest),
97
104
  React.createElement(CardContent, { className: classes.content },
@@ -2,7 +2,6 @@ import { __rest } from "tslib";
2
2
  import React, { useMemo, useState } from 'react';
3
3
  import { styled } from '@mui/material/styles';
4
4
  import { Divider, Icon, IconButton, List, ListItem, ListItemButton, Menu, MenuItem, SwipeableDrawer, useMediaQuery, useTheme } from '@mui/material';
5
- import { SCFeatureName } from '@selfcommunity/types';
6
5
  import { Link, SCPreferences, SCRoutes, UserUtils, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
7
6
  import classNames from 'classnames';
8
7
  import { useThemeProps } from '@mui/system';
@@ -34,7 +33,8 @@ const MenuRoot = styled(Menu, {
34
33
  const PREFERENCES = [
35
34
  SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED,
36
35
  SCPreferences.CONFIGURATIONS_POST_TYPE_ENABLED,
37
- SCPreferences.CONFIGURATIONS_DISCUSSION_TYPE_ENABLED
36
+ SCPreferences.CONFIGURATIONS_DISCUSSION_TYPE_ENABLED,
37
+ SCPreferences.ADDONS_LOYALTY_POINTS_COLLECTION
38
38
  ];
39
39
  /**
40
40
  * > API documentation for the Community-JS Navigation Settings Icon Button component. Learn about the available props and the CSS API.
@@ -118,7 +118,7 @@ export default function NavigationSettingsIconButton(inProps) {
118
118
  !preferences[SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED] && (React.createElement(ListItem, { className: classes.item, key: "connections" },
119
119
  React.createElement(ListItemButton, { component: Link, to: scRoutingContext.url(SCRoutes.USER_PROFILE_CONNECTIONS_ROUTE_NAME, scUserContext.user) },
120
120
  React.createElement(FormattedMessage, { id: "ui.navigationSettingsIconButton.connections", defaultMessage: "ui.navigationSettingsIconButton.connections" })))),
121
- scPreferences.features.includes(SCFeatureName.LOYALTY) && (React.createElement(ListItem, { className: classes.item, key: "loyaltyProgram" },
121
+ preferences[SCPreferences.ADDONS_LOYALTY_POINTS_COLLECTION] && (React.createElement(ListItem, { className: classes.item, key: "loyaltyProgram" },
122
122
  React.createElement(ListItemButton, { component: Link, to: scRoutingContext.url(SCRoutes.LOYALTY_ROUTE_NAME, {}) },
123
123
  React.createElement(FormattedMessage, { id: "ui.navigationSettingsIconButton.loyalty", defaultMessage: "ui.navigationSettingsIconButton.loyalty" })))),
124
124
  preferences[SCPreferences.CONFIGURATIONS_POST_TYPE_ENABLED] && (React.createElement(ListItem, { className: classes.item, key: "followedPosts" },
@@ -167,7 +167,7 @@ export default function NavigationSettingsIconButton(inProps) {
167
167
  React.createElement(FormattedMessage, { id: "ui.navigationSettingsIconButton.followers", defaultMessage: "ui.navigationSettingsIconButton.followers" }))),
168
168
  !preferences[SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED] && (React.createElement(MenuItem, { className: classes.item, key: "connections", component: Link, to: scRoutingContext.url(SCRoutes.USER_PROFILE_CONNECTIONS_ROUTE_NAME, scUserContext.user) },
169
169
  React.createElement(FormattedMessage, { id: "ui.navigationSettingsIconButton.connections", defaultMessage: "ui.navigationSettingsIconButton.connections" }))),
170
- scPreferences.features.includes(SCFeatureName.LOYALTY) && (React.createElement(MenuItem, { className: classes.item, key: "loyaltyProgram", component: Link, to: scRoutingContext.url(SCRoutes.LOYALTY_ROUTE_NAME, {}) },
170
+ preferences[SCPreferences.ADDONS_LOYALTY_POINTS_COLLECTION] && (React.createElement(MenuItem, { className: classes.item, key: "loyaltyProgram", component: Link, to: scRoutingContext.url(SCRoutes.LOYALTY_ROUTE_NAME, {}) },
171
171
  React.createElement(FormattedMessage, { id: "ui.navigationSettingsIconButton.loyalty", defaultMessage: "ui.navigationSettingsIconButton.loyalty" }))),
172
172
  preferences[SCPreferences.CONFIGURATIONS_POST_TYPE_ENABLED] && (React.createElement(MenuItem, { className: classes.item, key: "followedPosts", component: Link, to: scRoutingContext.url(SCRoutes.USER_PROFILE_FOLLOWED_POSTS_ROUTE_NAME, scUserContext.user) },
173
173
  React.createElement(FormattedMessage, { id: "ui.navigationSettingsIconButton.postsFollowed", defaultMessage: "ui.navigationSettingsIconButton.postsFollowed" }))),
@@ -11,7 +11,7 @@ import SearchAutocomplete from '../SearchAutocomplete';
11
11
  import NavigationSettingsIconButton from '../NavigationSettingsIconButton';
12
12
  import ComposerIconButton from '../ComposerIconButton';
13
13
  import { SCFeatureName } from '@selfcommunity/types';
14
- import { Link, SCPreferences, SCRoutes, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
14
+ import { Link, SCPreferences, SCRoutes, UserUtils, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
15
15
  import NavigationMenuIconButton from '../NavigationMenuIconButton';
16
16
  import { PREFIX } from './constants';
17
17
  const classes = {
@@ -100,6 +100,11 @@ export default function NavigationToolbar(inProps) {
100
100
  }, [scPreferences.preferences]);
101
101
  const privateMessagingEnabled = useMemo(() => scPreferences.features.includes(SCFeatureName.PRIVATE_MESSAGING), [scPreferences.features]);
102
102
  const groupsEnabled = useMemo(() => scPreferences.features.includes(SCFeatureName.GROUPING), [scPreferences.features]);
103
+ const showComposer = useMemo(() => {
104
+ return (scPreferences.preferences[SCPreferences.CONFIGURATIONS_POST_ONLY_STAFF_ENABLED].value &&
105
+ !disableComposer &&
106
+ (!scPreferences.preferences[SCPreferences.CONFIGURATIONS_POST_ONLY_STAFF_ENABLED].value || UserUtils.isStaff(scUserContext.user)));
107
+ }, [scPreferences, disableComposer, scUserContext.user]);
103
108
  // STATE
104
109
  const [anchorNotification, setAnchorNotification] = React.useState(null);
105
110
  // HANDLERS
@@ -121,7 +126,9 @@ export default function NavigationToolbar(inProps) {
121
126
  preferences[SCPreferences.CONFIGURATIONS_EXPLORE_STREAM_ENABLED] &&
122
127
  (preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY] || scUserContext.user) && (React.createElement(IconButton, { className: classNames(classes.explore, { [classes.active]: value.startsWith(scRoutingContext.url(SCRoutes.EXPLORE_ROUTE_NAME, {})) }), "aria-label": "Explore", to: scRoutingContext.url(SCRoutes.EXPLORE_ROUTE_NAME, {}), component: Link },
123
128
  React.createElement(Icon, null, "explore"))),
124
- groupsEnabled && scUserContext.user && (React.createElement(IconButton, { className: classNames(classes.groups, { [classes.active]: value.startsWith(scRoutingContext.url(SCRoutes.GROUPS_ROUTE_NAME, {})) }), "aria-label": "Groups", to: scRoutingContext.url(SCRoutes.GROUPS_ROUTE_NAME, {}), component: Link },
129
+ groupsEnabled && scUserContext.user && (React.createElement(IconButton, { className: classNames(classes.groups, {
130
+ [classes.active]: value.startsWith(scRoutingContext.url(SCRoutes.GROUPS_SUBSCRIBED_ROUTE_NAME, {}))
131
+ }), "aria-label": "Groups", to: scRoutingContext.url(SCRoutes.GROUPS_SUBSCRIBED_ROUTE_NAME, {}), component: Link },
125
132
  React.createElement(Icon, null, "groups")))));
126
133
  return (React.createElement(Root, Object.assign({ className: classNames(className, classes.root) }, rest),
127
134
  React.createElement(NavigationMenuIconButtonComponent, null),
@@ -133,7 +140,7 @@ export default function NavigationToolbar(inProps) {
133
140
  (preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY] || scUserContext.user) && !disableSearch ? (React.createElement(SearchAutocomplete, Object.assign({ className: classes.search, blurOnSelect: true }, SearchAutocompleteProps))) : (React.createElement(Box, { className: classes.search })),
134
141
  startActions,
135
142
  scUserContext.user ? (React.createElement(React.Fragment, null,
136
- !disableComposer && React.createElement(ComposerIconButton, Object.assign({ className: classes.composer }, ComposerIconButtonProps)),
143
+ showComposer && React.createElement(ComposerIconButton, Object.assign({ className: classes.composer }, ComposerIconButtonProps)),
137
144
  React.createElement(Tooltip, { title: scUserContext.user.username },
138
145
  React.createElement(IconButton, { component: Link, to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, scUserContext.user), "aria-label": "Profile", className: classes.profile },
139
146
  React.createElement(Avatar, { alt: scUserContext.user.username, src: scUserContext.user.avatar }))),