@selfcommunity/react-ui 0.7.9-alpha.9 → 0.7.10-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 (181) 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 +9 -1
  22. package/lib/cjs/components/Group/Group.js +18 -6
  23. package/lib/cjs/components/GroupAutocomplete/GroupAutocomplete.d.ts +0 -1
  24. package/lib/cjs/components/GroupAutocomplete/GroupAutocomplete.js +1 -2
  25. package/lib/cjs/components/GroupForm/GroupForm.js +64 -13
  26. package/lib/cjs/components/GroupHeader/GroupHeader.d.ts +2 -3
  27. package/lib/cjs/components/GroupHeader/GroupHeader.js +38 -5
  28. package/lib/cjs/components/GroupInfoWidget/GroupInfoWidget.js +65 -9
  29. package/lib/cjs/components/GroupInviteButton/GroupInviteButton.js +29 -7
  30. package/lib/cjs/components/GroupInvitedWidget/GroupInvitedWidget.d.ts +73 -0
  31. package/lib/cjs/components/GroupInvitedWidget/GroupInvitedWidget.js +220 -0
  32. package/lib/cjs/components/GroupInvitedWidget/Skeleton.d.ts +22 -0
  33. package/lib/cjs/components/GroupInvitedWidget/Skeleton.js +38 -0
  34. package/lib/cjs/components/GroupInvitedWidget/constants.d.ts +1 -0
  35. package/lib/cjs/components/GroupInvitedWidget/constants.js +4 -0
  36. package/lib/cjs/components/GroupInvitedWidget/index.d.ts +4 -0
  37. package/lib/cjs/components/GroupInvitedWidget/index.js +8 -0
  38. package/lib/cjs/components/GroupMembersButton/GroupMembersButton.js +6 -2
  39. package/lib/cjs/components/GroupMembersWidget/GroupMembersWidget.js +21 -6
  40. package/lib/cjs/components/GroupRequestsWidget/GroupRequestsWidget.d.ts +12 -2
  41. package/lib/cjs/components/GroupRequestsWidget/GroupRequestsWidget.js +13 -12
  42. package/lib/cjs/components/GroupSettingsIconButton/GroupSettingsIconButton.d.ts +4 -12
  43. package/lib/cjs/components/GroupSettingsIconButton/GroupSettingsIconButton.js +33 -19
  44. package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.d.ts +3 -3
  45. package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.js +22 -6
  46. package/lib/cjs/components/Groups/Groups.d.ts +15 -8
  47. package/lib/cjs/components/Groups/Groups.js +86 -32
  48. package/lib/cjs/components/Groups/Skeleton.d.ts +4 -0
  49. package/lib/cjs/components/Groups/Skeleton.js +2 -2
  50. package/lib/cjs/components/InlineComposerWidget/InlineComposerWidget.js +7 -0
  51. package/lib/cjs/components/NavigationSettingsIconButton/NavigationSettingsIconButton.js +4 -4
  52. package/lib/cjs/components/NavigationToolbar/NavigationToolbar.js +10 -2
  53. package/lib/cjs/components/NavigationToolbarMobile/NavigationToolbarMobile.d.ts +1 -0
  54. package/lib/cjs/components/NavigationToolbarMobile/NavigationToolbarMobile.js +9 -1
  55. package/lib/cjs/components/Notification/Group/Group.d.ts +15 -0
  56. package/lib/cjs/components/Notification/Group/Group.js +87 -0
  57. package/lib/cjs/components/Notification/Group/index.d.ts +3 -0
  58. package/lib/cjs/components/Notification/Group/index.js +5 -0
  59. package/lib/cjs/components/Notification/Notification.js +34 -1
  60. package/lib/cjs/components/Notification/PrivateMessage/PrivateMessage.js +16 -5
  61. package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.d.ts +7 -1
  62. package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.js +16 -8
  63. package/lib/cjs/components/PrivateMessageSettingsIconButton/PrivateMessageSettingsIconButton.js +1 -1
  64. package/lib/cjs/components/PrivateMessageSnippetItem/PrivateMessageSnippetItem.js +11 -6
  65. package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.d.ts +9 -4
  66. package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.js +24 -6
  67. package/lib/cjs/components/PrivateMessageThread/PrivateMessageThread.d.ts +6 -1
  68. package/lib/cjs/components/PrivateMessageThread/PrivateMessageThread.js +46 -20
  69. package/lib/cjs/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +6 -0
  70. package/lib/cjs/components/SearchAutocomplete/SearchAutocomplete.js +22 -5
  71. package/lib/cjs/components/SnippetNotifications/SnippetNotifications.js +7 -0
  72. package/lib/cjs/components/ToastNotifications/ToastNotifications.js +7 -0
  73. package/lib/cjs/components/User/User.d.ts +6 -1
  74. package/lib/cjs/components/User/User.js +5 -4
  75. package/lib/cjs/components/UserSubscribedGroupsWidget/Skeleton.d.ts +21 -0
  76. package/lib/cjs/components/UserSubscribedGroupsWidget/Skeleton.js +46 -0
  77. package/lib/cjs/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.d.ts +68 -0
  78. package/lib/cjs/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.js +183 -0
  79. package/lib/cjs/components/UserSubscribedGroupsWidget/constants.d.ts +1 -0
  80. package/lib/cjs/components/UserSubscribedGroupsWidget/constants.js +4 -0
  81. package/lib/cjs/components/UserSubscribedGroupsWidget/index.d.ts +4 -0
  82. package/lib/cjs/components/UserSubscribedGroupsWidget/index.js +8 -0
  83. package/lib/cjs/components/VoteAudienceButton/VoteAudienceButton.js +1 -1
  84. package/lib/cjs/constants/PubSub.d.ts +28 -0
  85. package/lib/cjs/constants/PubSub.js +22 -0
  86. package/lib/cjs/index.d.ts +5 -3
  87. package/lib/cjs/index.js +11 -4
  88. package/lib/cjs/types/index.d.ts +2 -1
  89. package/lib/esm/components/AccountRecover/AccountRecover.js +6 -1
  90. package/lib/esm/components/BottomNavigation/BottomNavigation.js +5 -4
  91. package/lib/esm/components/CategoryHeader/Skeleton.js +3 -2
  92. package/lib/esm/components/ChangeGroupCover/ChangeGroupCover.js +6 -6
  93. package/lib/esm/components/ChangeGroupPicture/ChangeGroupPicture.js +19 -16
  94. package/lib/esm/components/Composer/Attributes/Attributes.js +3 -3
  95. package/lib/esm/components/Composer/Composer.js +3 -3
  96. package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.d.ts +1 -1
  97. package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.js +9 -19
  98. package/lib/esm/components/Editor/Editor.js +2 -0
  99. package/lib/esm/components/Editor/nodes/ImageNode.js +6 -0
  100. package/lib/esm/components/Editor/plugins/ImagePlugin.js +4 -0
  101. package/lib/esm/components/Editor/plugins/ToolbarPlugin.js +19 -5
  102. package/lib/esm/components/FeedObject/Actions/Share/Share.js +19 -17
  103. package/lib/esm/components/FeedObject/Contributors/Contributors.js +1 -1
  104. package/lib/esm/components/FeedObject/FeedObject.d.ts +1 -0
  105. package/lib/esm/components/FeedObject/FeedObject.js +28 -9
  106. package/lib/esm/components/FeedObject/Poll/Poll.js +20 -20
  107. package/lib/esm/components/FeedUpdatesWidget/FeedUpdatesWidget.js +1 -1
  108. package/lib/esm/components/Footer/Footer.js +2 -2
  109. package/lib/esm/components/Group/Group.d.ts +9 -1
  110. package/lib/esm/components/Group/Group.js +22 -10
  111. package/lib/esm/components/GroupAutocomplete/GroupAutocomplete.d.ts +0 -1
  112. package/lib/esm/components/GroupAutocomplete/GroupAutocomplete.js +1 -2
  113. package/lib/esm/components/GroupForm/GroupForm.js +64 -13
  114. package/lib/esm/components/GroupHeader/GroupHeader.d.ts +2 -3
  115. package/lib/esm/components/GroupHeader/GroupHeader.js +40 -7
  116. package/lib/esm/components/GroupInfoWidget/GroupInfoWidget.js +65 -9
  117. package/lib/esm/components/GroupInviteButton/GroupInviteButton.js +29 -7
  118. package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.d.ts +73 -0
  119. package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.js +217 -0
  120. package/lib/esm/components/GroupInvitedWidget/Skeleton.d.ts +22 -0
  121. package/lib/esm/components/GroupInvitedWidget/Skeleton.js +34 -0
  122. package/lib/esm/components/GroupInvitedWidget/constants.d.ts +1 -0
  123. package/lib/esm/components/GroupInvitedWidget/constants.js +1 -0
  124. package/lib/esm/components/GroupInvitedWidget/index.d.ts +4 -0
  125. package/lib/esm/components/GroupInvitedWidget/index.js +4 -0
  126. package/lib/esm/components/GroupMembersButton/GroupMembersButton.js +7 -3
  127. package/lib/esm/components/GroupMembersWidget/GroupMembersWidget.js +22 -7
  128. package/lib/esm/components/GroupRequestsWidget/GroupRequestsWidget.d.ts +12 -2
  129. package/lib/esm/components/GroupRequestsWidget/GroupRequestsWidget.js +13 -12
  130. package/lib/esm/components/GroupSettingsIconButton/GroupSettingsIconButton.d.ts +4 -12
  131. package/lib/esm/components/GroupSettingsIconButton/GroupSettingsIconButton.js +33 -19
  132. package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.d.ts +3 -3
  133. package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.js +22 -6
  134. package/lib/esm/components/Groups/Groups.d.ts +15 -8
  135. package/lib/esm/components/Groups/Groups.js +91 -37
  136. package/lib/esm/components/Groups/Skeleton.d.ts +4 -0
  137. package/lib/esm/components/Groups/Skeleton.js +2 -2
  138. package/lib/esm/components/InlineComposerWidget/InlineComposerWidget.js +9 -2
  139. package/lib/esm/components/NavigationSettingsIconButton/NavigationSettingsIconButton.js +4 -4
  140. package/lib/esm/components/NavigationToolbar/NavigationToolbar.js +11 -3
  141. package/lib/esm/components/NavigationToolbarMobile/NavigationToolbarMobile.d.ts +1 -0
  142. package/lib/esm/components/NavigationToolbarMobile/NavigationToolbarMobile.js +11 -3
  143. package/lib/esm/components/Notification/Group/Group.d.ts +15 -0
  144. package/lib/esm/components/Notification/Group/Group.js +84 -0
  145. package/lib/esm/components/Notification/Group/index.d.ts +3 -0
  146. package/lib/esm/components/Notification/Group/index.js +2 -0
  147. package/lib/esm/components/Notification/Notification.js +34 -1
  148. package/lib/esm/components/Notification/PrivateMessage/PrivateMessage.js +16 -5
  149. package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.d.ts +7 -1
  150. package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.js +17 -9
  151. package/lib/esm/components/PrivateMessageSettingsIconButton/PrivateMessageSettingsIconButton.js +1 -1
  152. package/lib/esm/components/PrivateMessageSnippetItem/PrivateMessageSnippetItem.js +11 -6
  153. package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.d.ts +9 -4
  154. package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.js +26 -8
  155. package/lib/esm/components/PrivateMessageThread/PrivateMessageThread.d.ts +6 -1
  156. package/lib/esm/components/PrivateMessageThread/PrivateMessageThread.js +48 -22
  157. package/lib/esm/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +7 -1
  158. package/lib/esm/components/SearchAutocomplete/SearchAutocomplete.js +22 -5
  159. package/lib/esm/components/SnippetNotifications/SnippetNotifications.js +7 -0
  160. package/lib/esm/components/ToastNotifications/ToastNotifications.js +7 -0
  161. package/lib/esm/components/User/User.d.ts +6 -1
  162. package/lib/esm/components/User/User.js +5 -4
  163. package/lib/esm/components/UserSubscribedGroupsWidget/Skeleton.d.ts +21 -0
  164. package/lib/esm/components/UserSubscribedGroupsWidget/Skeleton.js +42 -0
  165. package/lib/esm/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.d.ts +68 -0
  166. package/lib/esm/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.js +180 -0
  167. package/lib/esm/components/UserSubscribedGroupsWidget/constants.d.ts +1 -0
  168. package/lib/esm/components/UserSubscribedGroupsWidget/constants.js +1 -0
  169. package/lib/esm/components/UserSubscribedGroupsWidget/index.d.ts +4 -0
  170. package/lib/esm/components/UserSubscribedGroupsWidget/index.js +4 -0
  171. package/lib/esm/components/VoteAudienceButton/VoteAudienceButton.js +1 -1
  172. package/lib/esm/constants/PubSub.d.ts +28 -0
  173. package/lib/esm/constants/PubSub.js +19 -0
  174. package/lib/esm/index.d.ts +5 -3
  175. package/lib/esm/index.js +4 -2
  176. package/lib/esm/types/index.d.ts +2 -1
  177. package/lib/umd/311.js +2 -0
  178. package/lib/umd/react-ui.js +1 -1
  179. package/package.json +10 -10
  180. package/lib/umd/871.js +0 -2
  181. /package/lib/umd/{871.js.LICENSE.txt → 311.js.LICENSE.txt} +0 -0
@@ -7,25 +7,17 @@ export interface GroupSettingsIconButtonProps extends IconButtonProps {
7
7
  */
8
8
  className?: string;
9
9
  /**
10
- * Handles callback on menu item delete click
10
+ * Handles callback on delete success
11
11
  */
12
- onMenuItemRemoveClick?: () => void;
13
- /**
14
- * Handles callback on delete confirm
15
- */
16
- onItemRemoveConfirm?: () => void;
17
- /**
18
- * The deleting thread id
19
- */
20
- userToRemove?: any;
12
+ onRemoveSuccess?: () => void;
21
13
  /**
22
14
  * The user
23
15
  */
24
- user?: SCUserType;
16
+ user: SCUserType;
25
17
  /**
26
18
  * The group obj
27
19
  */
28
- group?: SCGroupType;
20
+ group: SCGroupType;
29
21
  /**
30
22
  * Any other properties
31
23
  */
@@ -10,6 +10,9 @@ const classnames_1 = tslib_1.__importDefault(require("classnames"));
10
10
  const system_1 = require("@mui/system");
11
11
  const react_core_1 = require("@selfcommunity/react-core");
12
12
  const ConfirmDialog_1 = tslib_1.__importDefault(require("../../shared/ConfirmDialog/ConfirmDialog"));
13
+ const api_services_1 = require("@selfcommunity/api-services");
14
+ const PubSub_1 = require("../../constants/PubSub");
15
+ const pubsub_js_1 = tslib_1.__importDefault(require("pubsub-js"));
13
16
  const PREFIX = 'SCGroupSettingsIconButton';
14
17
  const classes = {
15
18
  root: `${PREFIX}-root`,
@@ -58,7 +61,7 @@ function GroupSettingsIconButton(inProps) {
58
61
  props: inProps,
59
62
  name: PREFIX
60
63
  });
61
- const { className = null, onMenuItemRemoveClick, group, user, onItemRemoveConfirm, userToRemove } = props, rest = tslib_1.__rest(props, ["className", "onMenuItemRemoveClick", "group", "user", "onItemRemoveConfirm", "userToRemove"]);
64
+ const { className = null, group, user, onRemoveSuccess } = props, rest = tslib_1.__rest(props, ["className", "group", "user", "onRemoveSuccess"]);
62
65
  // STATE
63
66
  const [anchorEl, setAnchorEl] = (0, react_1.useState)(null);
64
67
  const [openConfirmDialog, setOpenConfirmDialog] = (0, react_1.useState)(false);
@@ -82,22 +85,31 @@ function GroupSettingsIconButton(inProps) {
82
85
  const handleCloseDialog = () => {
83
86
  setOpenConfirmDialog(false);
84
87
  setAnchorEl(null);
85
- onItemRemoveConfirm && onItemRemoveConfirm();
86
88
  };
89
+ /**
90
+ * Notify UI when a user is removed from a group
91
+ * @param group
92
+ * @param user
93
+ */
94
+ function notifyChanges(group, user) {
95
+ if (group && user) {
96
+ pubsub_js_1.default.publish(`${PubSub_1.SCTopicType.GROUP}.${PubSub_1.SCEventType.REMOVE_MEMBER}`, { group, user });
97
+ }
98
+ }
87
99
  /**
88
100
  * Handles thread deletion
89
101
  */
90
102
  function handleRemoveUser() {
91
- console.log(userToRemove);
92
- // GroupService.removeUserFromGroup(group.id, userToRemove)
93
- // .then(() => {
94
- // PubSub.publish('snippetsChannelDelete', userToRemove);
95
- // handleCloseDialog();
96
- // })
97
- // .catch((error) => {
98
- // setOpenConfirmDialog(false);
99
- // console.log(error);
100
- // });
103
+ api_services_1.GroupService.removeUserFromGroup(group.id, user.id)
104
+ .then(() => {
105
+ notifyChanges(group, user);
106
+ onRemoveSuccess && onRemoveSuccess();
107
+ handleCloseDialog();
108
+ })
109
+ .catch((error) => {
110
+ setOpenConfirmDialog(false);
111
+ console.log(error);
112
+ });
101
113
  }
102
114
  if (scUserContext.user.id === user.id) {
103
115
  return null;
@@ -110,9 +122,7 @@ function GroupSettingsIconButton(inProps) {
110
122
  return [
111
123
  react_1.default.createElement(material_1.ListItem, { className: classes.item, key: "message", component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user) },
112
124
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" })),
113
- react_1.default.createElement(material_1.ListItem, { className: classes.item, key: "report", onClick: () => console.log('report') },
114
- react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.item.report", defaultMessage: "ui.groupSettingsIconButton.item.report" })),
115
- react_1.default.createElement(material_1.ListItem, { className: classes.item, key: "delete", onClick: userToRemove ? handleOpenDialog : onMenuItemRemoveClick },
125
+ react_1.default.createElement(material_1.ListItem, { className: classes.item, key: "delete", onClick: handleOpenDialog },
116
126
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.item.remove", defaultMessage: "ui.groupSettingsIconButton.item.remove" }))
117
127
  ];
118
128
  }
@@ -120,9 +130,7 @@ function GroupSettingsIconButton(inProps) {
120
130
  return [
121
131
  react_1.default.createElement(material_1.MenuItem, { className: classes.item, component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user), key: "message" },
122
132
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" })),
123
- react_1.default.createElement(material_1.MenuItem, { className: classes.item, onClick: () => console.log('report'), key: "report" },
124
- react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.item.report", defaultMessage: "ui.groupSettingsIconButton.item.report" })),
125
- react_1.default.createElement(material_1.MenuItem, { className: classes.item, onClick: userToRemove ? handleOpenDialog : onMenuItemRemoveClick, key: "delete" },
133
+ react_1.default.createElement(material_1.MenuItem, { className: classes.item, onClick: handleOpenDialog, key: "delete" },
126
134
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.item.remove", defaultMessage: "ui.groupSettingsIconButton.item.remove" }))
127
135
  ];
128
136
  }
@@ -132,6 +140,12 @@ function GroupSettingsIconButton(inProps) {
132
140
  react_1.default.createElement(Icon_1.default, null, "more_vert")),
133
141
  isMobile ? (react_1.default.createElement(SwipeableDrawerRoot, { className: classes.drawerRoot, anchor: "bottom", open: Boolean(anchorEl), onClose: handleClose, onOpen: handleOpen, PaperProps: { className: classes.paper }, disableSwipeToOpen: true },
134
142
  react_1.default.createElement(material_1.List, null, renderList()))) : (react_1.default.createElement(MenuRoot, { className: classes.menuRoot, anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, PaperProps: { className: classes.paper } }, renderList())),
135
- openConfirmDialog && (react_1.default.createElement(ConfirmDialog_1.default, { open: openConfirmDialog, title: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.dialog.msg", defaultMessage: "ui.groupSettingsIconButton.dialog.msg" }), btnConfirm: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.dialog.confirm", defaultMessage: "ui.groupSettingsIconButton.dialog.confirm" }), onConfirm: handleRemoveUser, onClose: handleCloseDialog }))));
143
+ openConfirmDialog && (react_1.default.createElement(ConfirmDialog_1.default, { open: openConfirmDialog, title: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.dialog.msg", defaultMessage: "ui.groupSettingsIconButton.dialog.msg", values: {
144
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
145
+ // @ts-ignore
146
+ b: (...chunks) => react_1.default.createElement("strong", null, chunks),
147
+ user: user.username,
148
+ group: group.name
149
+ } }), btnConfirm: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupSettingsIconButton.dialog.confirm", defaultMessage: "ui.groupSettingsIconButton.dialog.confirm" }), onConfirm: handleRemoveUser, onClose: handleCloseDialog }))));
136
150
  }
137
151
  exports.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,10 +16,10 @@ export interface GroupSubscribeButtonProps {
16
16
  */
17
17
  groupId?: number;
18
18
  /**
19
- * id of the user to be accepted into the group
19
+ * The user to be accepted into the group
20
20
  * @default null
21
21
  */
22
- userId?: number;
22
+ user?: SCUserType;
23
23
  /**
24
24
  * onSubscribe callback
25
25
  * @param user
@@ -11,6 +11,8 @@ const react_intl_1 = require("react-intl");
11
11
  const classnames_1 = tslib_1.__importDefault(require("classnames"));
12
12
  const system_1 = require("@mui/system");
13
13
  const Errors_1 = require("../../constants/Errors");
14
+ const PubSub_1 = require("../../constants/PubSub");
15
+ const pubsub_js_1 = tslib_1.__importDefault(require("pubsub-js"));
14
16
  const PREFIX = 'SCGroupSubscribeButton';
15
17
  const classes = {
16
18
  root: `${PREFIX}-root`
@@ -49,7 +51,7 @@ function GroupSubscribeButton(inProps) {
49
51
  props: inProps,
50
52
  name: PREFIX
51
53
  });
52
- const { className, groupId, group, userId, onSubscribe } = props, rest = tslib_1.__rest(props, ["className", "groupId", "group", "userId", "onSubscribe"]);
54
+ const { className, groupId, group, user, onSubscribe } = props, rest = tslib_1.__rest(props, ["className", "groupId", "group", "user", "onSubscribe"]);
53
55
  // STATE
54
56
  const [status, setStatus] = (0, react_1.useState)(null);
55
57
  // CONTEXT
@@ -73,11 +75,25 @@ function GroupSubscribeButton(inProps) {
73
75
  setStatus(scGroupsManager.subscriptionStatus(scGroup));
74
76
  }
75
77
  }, [authUserId, scGroupsManager.subscriptionStatus]);
76
- const subscribe = (userId) => {
78
+ /**
79
+ * Notify UI when a member is added to a group
80
+ * @param group
81
+ * @param user
82
+ */
83
+ function notifyChanges(group, user) {
84
+ if (group && user) {
85
+ pubsub_js_1.default.publish(`${PubSub_1.SCTopicType.GROUP}.${PubSub_1.SCEventType.ADD_MEMBER}`, { group, user });
86
+ }
87
+ }
88
+ const subscribe = (user) => {
77
89
  scGroupsManager
78
- .subscribe(scGroup, userId)
90
+ .subscribe(scGroup, user === null || user === void 0 ? void 0 : user.id)
79
91
  .then(() => {
80
- onSubscribe && onSubscribe(scGroup, types_1.SCGroupSubscriptionStatusType.SUBSCRIBED);
92
+ const _status = scGroup.privacy === types_1.SCGroupPrivacyType.PRIVATE && scGroup.subscription_status !== types_1.SCGroupSubscriptionStatusType.INVITED
93
+ ? types_1.SCGroupSubscriptionStatusType.REQUESTED
94
+ : types_1.SCGroupSubscriptionStatusType.SUBSCRIBED;
95
+ notifyChanges(scGroup, user);
96
+ onSubscribe && onSubscribe(scGroup, _status);
81
97
  })
82
98
  .catch((e) => {
83
99
  utils_1.Logger.error(Errors_1.SCOPE_SC_UI, e);
@@ -98,7 +114,7 @@ function GroupSubscribeButton(inProps) {
98
114
  scContext.settings.handleAnonymousAction();
99
115
  }
100
116
  else {
101
- status === types_1.SCGroupSubscriptionStatusType.SUBSCRIBED && !userId ? unsubscribe() : userId ? subscribe(userId) : subscribe();
117
+ status === types_1.SCGroupSubscriptionStatusType.SUBSCRIBED && !(user === null || user === void 0 ? void 0 : user.id) ? unsubscribe() : (user === null || user === void 0 ? void 0 : user.id) ? subscribe(user) : subscribe();
102
118
  }
103
119
  };
104
120
  /**
@@ -124,7 +140,7 @@ function GroupSubscribeButton(inProps) {
124
140
  }
125
141
  return _status;
126
142
  };
127
- if (!scGroup || (isGroupAdmin && userId === scUserContext.user.id)) {
143
+ 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))) {
128
144
  return null;
129
145
  }
130
146
  return (react_1.default.createElement(Root, Object.assign({ size: "small", variant: "outlined", onClick: handleSubscribeAction, loading: scUserContext.user ? scGroupsManager.isLoading(scGroup) : null, disabled: status === types_1.SCGroupSubscriptionStatusType.REQUESTED, className: (0, classnames_1.default)(classes.root, className) }, rest), isGroupAdmin ? react_1.default.createElement(react_intl_1.FormattedMessage, { defaultMessage: "ui.groupSubscribeButton.accept", id: "ui.groupSubscribeButton.accept" }) : getStatus()));
@@ -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 true
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
  */
@@ -14,9 +14,12 @@ const Errors_1 = require("../../constants/Errors");
14
14
  const system_1 = require("@mui/system");
15
15
  const HiddenPlaceholder_1 = tslib_1.__importDefault(require("../../shared/HiddenPlaceholder"));
16
16
  const constants_1 = require("./constants");
17
- const Group_1 = tslib_1.__importDefault(require("../Group"));
17
+ const Group_1 = tslib_1.__importStar(require("../Group"));
18
+ const Pagination_1 = require("../../constants/Pagination");
19
+ const InfiniteScroll_1 = tslib_1.__importDefault(require("../../shared/InfiniteScroll"));
18
20
  const classes = {
19
21
  root: `${constants_1.PREFIX}-root`,
22
+ filters: `${constants_1.PREFIX}-filter`,
20
23
  groups: `${constants_1.PREFIX}-groups`,
21
24
  item: `${constants_1.PREFIX}-item`,
22
25
  noResults: `${constants_1.PREFIX}-no-results`,
@@ -64,10 +67,14 @@ function Groups(inProps) {
64
67
  props: inProps,
65
68
  name: constants_1.PREFIX
66
69
  });
67
- const { endpoint, className, GroupComponentProps = { variant: 'outlined', ButtonBaseProps: { disableRipple: true, component: material_1.Box } }, prefetchedGroups = [] } = props, rest = tslib_1.__rest(props, ["endpoint", "className", "GroupComponentProps", "prefetchedGroups"]);
70
+ const { endpointQueryParams = { limit: 20, offset: Pagination_1.DEFAULT_PAGINATION_OFFSET }, className, GroupComponentProps = { variant: 'outlined', ButtonBaseProps: { disableRipple: true, component: material_1.Box } }, showFilters = true, filters, general = true } = props, rest = tslib_1.__rest(props, ["endpointQueryParams", "className", "GroupComponentProps", "showFilters", "filters", "general"]);
68
71
  // STATE
69
72
  const [groups, setGroups] = (0, react_1.useState)([]);
70
73
  const [loading, setLoading] = (0, react_1.useState)(true);
74
+ const [next, setNext] = (0, react_1.useState)(null);
75
+ const [search, setSearch] = (0, react_1.useState)('');
76
+ const theme = (0, material_1.useTheme)();
77
+ const isMobile = (0, material_1.useMediaQuery)(theme.breakpoints.down('md'));
71
78
  // CONTEXT
72
79
  const scUserContext = (0, react_core_1.useSCUser)();
73
80
  const scPreferencesContext = (0, react_core_1.useSCPreferences)();
@@ -76,19 +83,31 @@ function Groups(inProps) {
76
83
  scPreferencesContext.preferences[react_core_1.SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY].value, [scPreferencesContext.preferences]);
77
84
  // CONST
78
85
  const authUserId = scUserContext.user ? scUserContext.user.id : null;
79
- // REFS
80
- const isMountedRef = (0, react_core_1.useIsComponentMountedRef)();
86
+ // HANDLERS
87
+ const handleScrollUp = () => {
88
+ window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
89
+ };
81
90
  /**
82
91
  * Fetches groups list
83
92
  */
84
- const fetchGroups = (next = endpoint.url({})) => tslib_1.__awaiter(this, void 0, void 0, function* () {
85
- const response = yield api_services_1.http.request({
86
- url: next,
87
- method: endpoint.method
93
+ const fetchGroups = () => {
94
+ let groupService;
95
+ if (general) {
96
+ groupService = api_services_1.GroupService.searchGroups(Object.assign(Object.assign({}, endpointQueryParams), (search !== '' && { search: search })));
97
+ }
98
+ else {
99
+ groupService = api_services_1.GroupService.getUserGroups(Object.assign(Object.assign({}, endpointQueryParams), (search !== '' && { search: search })));
100
+ }
101
+ groupService
102
+ .then((res) => {
103
+ setGroups(res.results);
104
+ setNext(res.next);
105
+ setLoading(false);
106
+ })
107
+ .catch((error) => {
108
+ utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
88
109
  });
89
- const data = response.data;
90
- return data.next ? data.results.concat(yield fetchGroups(data.next)) : data.results;
91
- });
110
+ };
92
111
  /**
93
112
  * On mount, fetches groups list
94
113
  */
@@ -96,33 +115,68 @@ function Groups(inProps) {
96
115
  if (!contentAvailability && !authUserId) {
97
116
  return;
98
117
  }
99
- else if (prefetchedGroups.length) {
100
- setGroups(prefetchedGroups);
101
- setLoading(false);
102
- }
103
118
  else {
104
- fetchGroups()
105
- .then((data) => {
106
- if (isMountedRef.current) {
107
- setGroups(data);
108
- setLoading(false);
109
- }
110
- })
111
- .catch((error) => {
112
- utils_1.Logger.error(Errors_1.SCOPE_SC_UI, error);
113
- });
119
+ fetchGroups();
120
+ }
121
+ }, [contentAvailability, authUserId, search]);
122
+ const handleNext = (0, react_1.useMemo)(() => () => {
123
+ if (!next) {
124
+ return;
114
125
  }
115
- }, [contentAvailability, authUserId, prefetchedGroups.length]);
126
+ return api_services_1.http
127
+ .request({
128
+ url: next,
129
+ method: general ? api_services_1.Endpoints.SearchGroups.method : api_services_1.Endpoints.GetUserGroups.method
130
+ })
131
+ .then((res) => {
132
+ setGroups([...groups, ...res.data.results]);
133
+ setNext(res.data.next);
134
+ })
135
+ .catch((error) => console.log(error))
136
+ .then(() => setLoading(false));
137
+ }, [next]);
138
+ /**
139
+ * Get groups filtered
140
+ */
141
+ const getFilteredGroups = () => {
142
+ if (search) {
143
+ return groups.filter((g) => g.name.toLowerCase().includes(search.toLowerCase()));
144
+ }
145
+ return groups;
146
+ };
147
+ /**
148
+ * Handle change filter name
149
+ * @param event
150
+ */
151
+ const handleOnChangeFilterName = (event) => {
152
+ setSearch(event.target.value);
153
+ };
154
+ /**
155
+ * Renders groups list
156
+ */
157
+ const filteredGroups = (0, utils_1.sortByAttr)(getFilteredGroups(), 'order');
158
+ const content = (react_1.default.createElement(react_1.default.Fragment, null,
159
+ showFilters && groups.length !== 0 && (react_1.default.createElement(material_1.Grid, { container: true, direction: "row", justifyContent: "center", alignItems: "center", className: classes.filters }, filters ? (filters) : (react_1.default.createElement(material_1.Grid, { item: true, xs: 12, md: 6 },
160
+ react_1.default.createElement(material_1.TextField, { fullWidth: true, value: search, label: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groups.filterByName", defaultMessage: "ui.groups.filterByName" }), variant: "outlined", onChange: handleOnChangeFilterName, disabled: loading }))))),
161
+ react_1.default.createElement(react_1.default.Fragment, null, !groups.length ? (react_1.default.createElement(material_1.Box, { className: classes.noResults },
162
+ react_1.default.createElement(material_1.Typography, { variant: "h4" },
163
+ react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groups.noGroups.title", defaultMessage: "ui.groups.noGroups.title" })),
164
+ react_1.default.createElement(material_1.Typography, { variant: "body1" },
165
+ react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groups.noGroups.subtitle", defaultMessage: "ui.groups.noGroups.subtitle" })))) : (react_1.default.createElement(InfiniteScroll_1.default, { dataLength: groups.length, next: handleNext, hasMoreNext: Boolean(next), loaderNext: isMobile ? react_1.default.createElement(Group_1.GroupSkeleton, null) : react_1.default.createElement(Skeleton_1.default, { groupsNumber: 2 }), endMessage: react_1.default.createElement(material_1.Typography, { component: "div", className: classes.endMessage },
166
+ react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groups.endMessage", defaultMessage: "ui.groups.endMessage", values: {
167
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
168
+ // @ts-ignore
169
+ button: (chunk) => (react_1.default.createElement(material_1.Button, { color: "secondary", variant: "text", onClick: handleScrollUp }, chunk))
170
+ } })) },
171
+ react_1.default.createElement(material_1.Grid, { container: true, spacing: { xs: 2 }, className: classes.groups }, filteredGroups.map((group) => (react_1.default.createElement(material_1.Grid, { item: true, xs: 12, sm: 8, md: 6, key: group.id, className: classes.item },
172
+ react_1.default.createElement(Group_1.default, Object.assign({ group: group, groupId: group.id, actionRedirect: true }, GroupComponentProps)))))))))));
116
173
  // RENDER
117
174
  if (!contentAvailability && !scUserContext.user) {
118
175
  return react_1.default.createElement(HiddenPlaceholder_1.default, null);
119
176
  }
120
- const content = (react_1.default.createElement(react_1.default.Fragment, null, loading ? (react_1.default.createElement(Skeleton_1.default, null)) : (react_1.default.createElement(material_1.Grid, { container: true, spacing: { xs: 3 }, className: classes.groups }, !groups.length ? (react_1.default.createElement(material_1.Box, { className: classes.noResults },
121
- react_1.default.createElement(material_1.Typography, { variant: "h4" },
122
- react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groups.noGroups.title", defaultMessage: "ui.groups.noGroups.title" })),
123
- react_1.default.createElement(material_1.Typography, { variant: "body1" },
124
- react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groups.noGroups.subtitle", defaultMessage: "ui.groups.noGroups.subtitle" })))) : (react_1.default.createElement(react_1.default.Fragment, null, groups.map((group) => (react_1.default.createElement(material_1.Grid, { item: true, xs: 12, sm: 8, md: 6, key: group.id, className: classes.item },
125
- react_1.default.createElement(Group_1.default, Object.assign({ group: group, groupId: group.id }, GroupComponentProps)))))))))));
177
+ if (loading) {
178
+ return react_1.default.createElement(Skeleton_1.default, null);
179
+ }
126
180
  return (react_1.default.createElement(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, rest), content));
127
181
  }
128
182
  exports.default = Groups;
@@ -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.
@@ -37,9 +37,9 @@ const Root = (0, styles_1.styled)(material_1.Box, {
37
37
  *
38
38
  */
39
39
  function GroupsSkeleton(inProps) {
40
- const { className, GroupSkeletonProps = {} } = inProps, rest = tslib_1.__rest(inProps, ["className", "GroupSkeletonProps"]);
40
+ const { className, GroupSkeletonProps = {}, groupsNumber = 20 } = inProps, rest = tslib_1.__rest(inProps, ["className", "GroupSkeletonProps", "groupsNumber"]);
41
41
  return (react_1.default.createElement(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, rest),
42
- react_1.default.createElement(material_1.Grid, { container: true, spacing: { xs: 3 }, className: classes.groups }, [...Array(15)].map((category, index) => (react_1.default.createElement(material_1.Grid, { item: true, xs: 12, sm: 8, md: 6, key: index },
42
+ react_1.default.createElement(material_1.Grid, { container: true, spacing: { xs: 3 }, className: classes.groups }, [...Array(groupsNumber)].map((category, index) => (react_1.default.createElement(material_1.Grid, { item: true, xs: 12, sm: 8, md: 6, key: index },
43
43
  react_1.default.createElement(Group_1.GroupSkeleton, Object.assign({ elevation: 0, variant: 'outlined' }, GroupSkeletonProps))))))));
44
44
  }
45
45
  exports.default = GroupsSkeleton;
@@ -12,6 +12,7 @@ const system_1 = require("@mui/system");
12
12
  const Composer_1 = tslib_1.__importDefault(require("../Composer"));
13
13
  const Media_1 = require("../../shared/Media");
14
14
  const constants_1 = require("./constants");
15
+ const HiddenPlaceholder_1 = tslib_1.__importDefault(require("../../shared/HiddenPlaceholder"));
15
16
  const classes = {
16
17
  root: `${constants_1.PREFIX}-root`,
17
18
  content: `${constants_1.PREFIX}-content`,
@@ -60,6 +61,9 @@ function InlineComposerWidget(inProps) {
60
61
  const scUserContext = (0, react_core_1.useSCUser)();
61
62
  const scRoutingContext = (0, react_core_1.useSCRouting)();
62
63
  const { enqueueSnackbar } = (0, notistack_1.useSnackbar)();
64
+ // PREFERENCES
65
+ const preferences = (0, react_core_1.useSCPreferences)();
66
+ const onlyStaffEnabled = (0, react_1.useMemo)(() => preferences.preferences[react_core_1.SCPreferences.CONFIGURATIONS_POST_ONLY_STAFF_ENABLED].value, [preferences.preferences]);
63
67
  // State variables
64
68
  const [open, setOpen] = (0, react_1.useState)(false);
65
69
  // Handlers
@@ -94,6 +98,9 @@ function InlineComposerWidget(inProps) {
94
98
  }
95
99
  setOpen(false);
96
100
  };
101
+ if (!react_core_1.UserUtils.isStaff(scUserContext.user) && onlyStaffEnabled) {
102
+ return react_1.default.createElement(HiddenPlaceholder_1.default, null);
103
+ }
97
104
  return (react_1.default.createElement(react_1.default.Fragment, null,
98
105
  react_1.default.createElement(Root, Object.assign({ className: classes.root }, rest),
99
106
  react_1.default.createElement(material_1.CardContent, { className: classes.content },
@@ -4,7 +4,6 @@ const tslib_1 = require("tslib");
4
4
  const react_1 = tslib_1.__importStar(require("react"));
5
5
  const styles_1 = require("@mui/material/styles");
6
6
  const material_1 = require("@mui/material");
7
- const types_1 = require("@selfcommunity/types");
8
7
  const react_core_1 = require("@selfcommunity/react-core");
9
8
  const classnames_1 = tslib_1.__importDefault(require("classnames"));
10
9
  const system_1 = require("@mui/system");
@@ -36,7 +35,8 @@ const MenuRoot = (0, styles_1.styled)(material_1.Menu, {
36
35
  const PREFERENCES = [
37
36
  react_core_1.SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED,
38
37
  react_core_1.SCPreferences.CONFIGURATIONS_POST_TYPE_ENABLED,
39
- react_core_1.SCPreferences.CONFIGURATIONS_DISCUSSION_TYPE_ENABLED
38
+ react_core_1.SCPreferences.CONFIGURATIONS_DISCUSSION_TYPE_ENABLED,
39
+ react_core_1.SCPreferences.ADDONS_LOYALTY_POINTS_COLLECTION
40
40
  ];
41
41
  /**
42
42
  * > API documentation for the Community-JS Navigation Settings Icon Button component. Learn about the available props and the CSS API.
@@ -120,7 +120,7 @@ function NavigationSettingsIconButton(inProps) {
120
120
  !preferences[react_core_1.SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED] && (react_1.default.createElement(material_1.ListItem, { className: classes.item, key: "connections" },
121
121
  react_1.default.createElement(material_1.ListItemButton, { component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_CONNECTIONS_ROUTE_NAME, scUserContext.user) },
122
122
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.navigationSettingsIconButton.connections", defaultMessage: "ui.navigationSettingsIconButton.connections" })))),
123
- scPreferences.features.includes(types_1.SCFeatureName.LOYALTY) && (react_1.default.createElement(material_1.ListItem, { className: classes.item, key: "loyaltyProgram" },
123
+ preferences[react_core_1.SCPreferences.ADDONS_LOYALTY_POINTS_COLLECTION] && (react_1.default.createElement(material_1.ListItem, { className: classes.item, key: "loyaltyProgram" },
124
124
  react_1.default.createElement(material_1.ListItemButton, { component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.LOYALTY_ROUTE_NAME, {}) },
125
125
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.navigationSettingsIconButton.loyalty", defaultMessage: "ui.navigationSettingsIconButton.loyalty" })))),
126
126
  preferences[react_core_1.SCPreferences.CONFIGURATIONS_POST_TYPE_ENABLED] && (react_1.default.createElement(material_1.ListItem, { className: classes.item, key: "followedPosts" },
@@ -169,7 +169,7 @@ function NavigationSettingsIconButton(inProps) {
169
169
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.navigationSettingsIconButton.followers", defaultMessage: "ui.navigationSettingsIconButton.followers" }))),
170
170
  !preferences[react_core_1.SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED] && (react_1.default.createElement(material_1.MenuItem, { className: classes.item, key: "connections", component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_CONNECTIONS_ROUTE_NAME, scUserContext.user) },
171
171
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.navigationSettingsIconButton.connections", defaultMessage: "ui.navigationSettingsIconButton.connections" }))),
172
- scPreferences.features.includes(types_1.SCFeatureName.LOYALTY) && (react_1.default.createElement(material_1.MenuItem, { className: classes.item, key: "loyaltyProgram", component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.LOYALTY_ROUTE_NAME, {}) },
172
+ preferences[react_core_1.SCPreferences.ADDONS_LOYALTY_POINTS_COLLECTION] && (react_1.default.createElement(material_1.MenuItem, { className: classes.item, key: "loyaltyProgram", component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.LOYALTY_ROUTE_NAME, {}) },
173
173
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.navigationSettingsIconButton.loyalty", defaultMessage: "ui.navigationSettingsIconButton.loyalty" }))),
174
174
  preferences[react_core_1.SCPreferences.CONFIGURATIONS_POST_TYPE_ENABLED] && (react_1.default.createElement(material_1.MenuItem, { className: classes.item, key: "followedPosts", component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_FOLLOWED_POSTS_ROUTE_NAME, scUserContext.user) },
175
175
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.navigationSettingsIconButton.postsFollowed", defaultMessage: "ui.navigationSettingsIconButton.postsFollowed" }))),
@@ -102,6 +102,11 @@ function NavigationToolbar(inProps) {
102
102
  }, [scPreferences.preferences]);
103
103
  const privateMessagingEnabled = (0, react_1.useMemo)(() => scPreferences.features.includes(types_1.SCFeatureName.PRIVATE_MESSAGING), [scPreferences.features]);
104
104
  const groupsEnabled = (0, react_1.useMemo)(() => scPreferences.features.includes(types_1.SCFeatureName.GROUPING), [scPreferences.features]);
105
+ const showComposer = (0, react_1.useMemo)(() => {
106
+ return (scPreferences.preferences[react_core_1.SCPreferences.CONFIGURATIONS_POST_ONLY_STAFF_ENABLED].value &&
107
+ !disableComposer &&
108
+ (!scPreferences.preferences[react_core_1.SCPreferences.CONFIGURATIONS_POST_ONLY_STAFF_ENABLED].value || react_core_1.UserUtils.isStaff(scUserContext.user)));
109
+ }, [scPreferences, disableComposer, scUserContext.user]);
105
110
  // STATE
106
111
  const [anchorNotification, setAnchorNotification] = react_1.default.useState(null);
107
112
  // HANDLERS
@@ -123,7 +128,10 @@ function NavigationToolbar(inProps) {
123
128
  preferences[react_core_1.SCPreferences.CONFIGURATIONS_EXPLORE_STREAM_ENABLED] &&
124
129
  (preferences[react_core_1.SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY] || scUserContext.user) && (react_1.default.createElement(material_1.IconButton, { className: (0, classnames_1.default)(classes.explore, { [classes.active]: value.startsWith(scRoutingContext.url(react_core_1.SCRoutes.EXPLORE_ROUTE_NAME, {})) }), "aria-label": "Explore", to: scRoutingContext.url(react_core_1.SCRoutes.EXPLORE_ROUTE_NAME, {}), component: react_core_1.Link },
125
130
  react_1.default.createElement(Icon_1.default, null, "explore"))),
126
- groupsEnabled && scUserContext.user && (react_1.default.createElement(material_1.IconButton, { className: (0, classnames_1.default)(classes.groups, { [classes.active]: value.startsWith(scRoutingContext.url(react_core_1.SCRoutes.GROUPS_ROUTE_NAME, {})) }), "aria-label": "Groups", to: scRoutingContext.url(react_core_1.SCRoutes.GROUPS_ROUTE_NAME, {}), component: react_core_1.Link },
131
+ groupsEnabled && scUserContext.user && (react_1.default.createElement(material_1.IconButton, { className: (0, classnames_1.default)(classes.groups, {
132
+ [classes.active]: value.startsWith(scRoutingContext.url(react_core_1.SCRoutes.GROUPS_SUBSCRIBED_ROUTE_NAME, {})) ||
133
+ value.startsWith(scRoutingContext.url(react_core_1.SCRoutes.GROUPS_ROUTE_NAME, {}))
134
+ }), "aria-label": "Groups", to: scRoutingContext.url(react_core_1.SCRoutes.GROUPS_SUBSCRIBED_ROUTE_NAME, {}), component: react_core_1.Link },
127
135
  react_1.default.createElement(Icon_1.default, null, "groups")))));
128
136
  return (react_1.default.createElement(Root, Object.assign({ className: (0, classnames_1.default)(className, classes.root) }, rest),
129
137
  react_1.default.createElement(NavigationMenuIconButtonComponent, null),
@@ -135,7 +143,7 @@ function NavigationToolbar(inProps) {
135
143
  (preferences[react_core_1.SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY] || scUserContext.user) && !disableSearch ? (react_1.default.createElement(SearchAutocomplete_1.default, Object.assign({ className: classes.search, blurOnSelect: true }, SearchAutocompleteProps))) : (react_1.default.createElement(material_1.Box, { className: classes.search })),
136
144
  startActions,
137
145
  scUserContext.user ? (react_1.default.createElement(react_1.default.Fragment, null,
138
- !disableComposer && react_1.default.createElement(ComposerIconButton_1.default, Object.assign({ className: classes.composer }, ComposerIconButtonProps)),
146
+ showComposer && react_1.default.createElement(ComposerIconButton_1.default, Object.assign({ className: classes.composer }, ComposerIconButtonProps)),
139
147
  react_1.default.createElement(material_1.Tooltip, { title: scUserContext.user.username },
140
148
  react_1.default.createElement(material_1.IconButton, { component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, scUserContext.user), "aria-label": "Profile", className: classes.profile },
141
149
  react_1.default.createElement(material_1.Avatar, { alt: scUserContext.user.username, src: scUserContext.user.avatar }))),
@@ -59,6 +59,7 @@ export interface NavigationToolbarMobileProps extends ToolbarProps {
59
59
  |logo|.SCNavigationToolbarMobile-logo|Styles applied to the logo element.|
60
60
  |search|.SCNavigationToolbarMobile-search|Styles applied to the search button element|
61
61
  |searchDialog|.SCNavigationToolbarMobile-search-dialog|Styles applied to the search dialog element|
62
+ |notifications|.SCNavigationToolbarMobile-notifications|Styles applied to the notifications button element|
62
63
  |settings|.SCNavigationToolbarMobile-settings|Styles applied to the settings button element|
63
64
  |settingsDialog|.SCNavigationToolbarMobile-settingsDialog|Styles applied to the settings dialog elements|
64
65
  |login|.SCNavigationToolbarMobile-login|Styles applied to the login element.|
@@ -13,11 +13,13 @@ const SearchDialog_1 = tslib_1.__importDefault(require("../SearchDialog"));
13
13
  const NavigationSettingsIconButton_1 = tslib_1.__importDefault(require("../NavigationSettingsIconButton"));
14
14
  const NavigationMenuIconButton_1 = tslib_1.__importDefault(require("../NavigationMenuIconButton"));
15
15
  const constants_1 = require("./constants");
16
+ const types_1 = require("@selfcommunity/types");
16
17
  const classes = {
17
18
  root: `${constants_1.PREFIX}-root`,
18
19
  logo: `${constants_1.PREFIX}-logo`,
19
20
  search: `${constants_1.PREFIX}-search`,
20
21
  searchDialog: `${constants_1.PREFIX}-search-dialog`,
22
+ notifications: `${constants_1.PREFIX}-notifications`,
21
23
  settings: `${constants_1.PREFIX}-settings`,
22
24
  settingsDialog: `${constants_1.PREFIX}-settings-dialog`,
23
25
  login: `${constants_1.PREFIX}-login`
@@ -52,6 +54,7 @@ const Root = (0, material_1.styled)(material_1.Toolbar, {
52
54
  |logo|.SCNavigationToolbarMobile-logo|Styles applied to the logo element.|
53
55
  |search|.SCNavigationToolbarMobile-search|Styles applied to the search button element|
54
56
  |searchDialog|.SCNavigationToolbarMobile-search-dialog|Styles applied to the search dialog element|
57
+ |notifications|.SCNavigationToolbarMobile-notifications|Styles applied to the notifications button element|
55
58
  |settings|.SCNavigationToolbarMobile-settings|Styles applied to the settings button element|
56
59
  |settingsDialog|.SCNavigationToolbarMobile-settingsDialog|Styles applied to the settings dialog elements|
57
60
  |login|.SCNavigationToolbarMobile-login|Styles applied to the login element.|
@@ -69,9 +72,11 @@ function NavigationToolbarMobile(inProps) {
69
72
  const scUserContext = (0, react_core_1.useSCUser)();
70
73
  const scRoutingContext = (0, react_core_1.useSCRouting)();
71
74
  // PREFERENCES
72
- const { preferences } = (0, react_core_1.useSCPreferences)();
75
+ const { preferences, features } = (0, react_core_1.useSCPreferences)();
73
76
  // STATE
74
77
  const [searchOpen, setSearchOpen] = (0, react_1.useState)(false);
78
+ // MEMO
79
+ const groupsEnabled = (0, react_1.useMemo)(() => features.includes(types_1.SCFeatureName.GROUPING), [features]);
75
80
  // HANDLERS
76
81
  const handleOpenSearch = (0, react_1.useCallback)(() => {
77
82
  setSearchOpen(true);
@@ -94,6 +99,9 @@ function NavigationToolbarMobile(inProps) {
94
99
  react_1.default.createElement(Icon_1.default, null, "search")),
95
100
  react_1.default.createElement(SearchDialog_1.default, { className: classes.searchDialog, fullScreen: true, open: searchOpen, SearchAutocompleteProps: Object.assign(Object.assign({}, SearchAutocompleteProps), { onClear: handleCloseSearch }) }))),
96
101
  endActions,
102
+ scUserContext.user && groupsEnabled && (react_1.default.createElement(material_1.IconButton, { className: classes.notifications, component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.USER_NOTIFICATIONS_ROUTE_NAME, {}) },
103
+ react_1.default.createElement(material_1.Badge, { badgeContent: scUserContext.user.unseen_notification_banners_counter + scUserContext.user.unseen_interactions_counter, color: "secondary" },
104
+ react_1.default.createElement(Icon_1.default, null, "notifications_active")))),
97
105
  scUserContext.user ? (react_1.default.createElement(NavigationSettingsIconButtonComponent, { className: classes.settings })) : (react_1.default.createElement(material_1.Button, { className: classes.login, color: "inherit", component: react_core_1.Link, to: scRoutingContext.url(react_core_1.SCRoutes.SIGNIN_ROUTE_NAME, {}) },
98
106
  react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.appBar.navigation.login", defaultMessage: "ui.appBar.navigation.login" })))));
99
107
  }
@@ -0,0 +1,15 @@
1
+ import { SCNotificationGroupActivityType } from '@selfcommunity/types';
2
+ import { NotificationItemProps } from '../../../shared/NotificationItem';
3
+ export interface NotificationGroupProps extends Pick<NotificationItemProps, Exclude<keyof NotificationItemProps, 'image' | 'disableTypography' | 'primary' | 'primaryTypographyProps' | 'secondary' | 'secondaryTypographyProps' | 'actions' | 'footer' | 'isNew'>> {
4
+ /**
5
+ * Notification obj
6
+ * @default null
7
+ */
8
+ notificationObject: SCNotificationGroupActivityType;
9
+ }
10
+ /**
11
+ * This component render the content of the notification of type group
12
+ * @constructor
13
+ * @param props
14
+ */
15
+ export default function GroupNotification(props: NotificationGroupProps): JSX.Element;