@selfcommunity/react-ui 0.7.9-alpha.9 → 0.7.9

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 +63 -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 +9 -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 +78 -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 +31 -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 +63 -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 +10 -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 +75 -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 +31 -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
@@ -0,0 +1,217 @@
1
+ import { __rest } from "tslib";
2
+ import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react';
3
+ import { styled } from '@mui/material/styles';
4
+ import List from '@mui/material/List';
5
+ import { Button, CardContent, ListItem, Typography, useMediaQuery, useTheme } from '@mui/material';
6
+ import Widget from '../Widget';
7
+ import { http, Endpoints, GroupService } from '@selfcommunity/api-services';
8
+ import { CacheStrategies, isInteger, Logger } from '@selfcommunity/utils';
9
+ import { SCCache, SCPreferences, useSCFetchGroup, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
10
+ import { actionWidgetTypes, dataWidgetReducer, stateWidgetInitializer } from '../../utils/widget';
11
+ import Skeleton from './Skeleton';
12
+ import { FormattedMessage } from 'react-intl';
13
+ import classNames from 'classnames';
14
+ import { SCOPE_SC_UI } from '../../constants/Errors';
15
+ import BaseDialog from '../../shared/BaseDialog';
16
+ import InfiniteScroll from '../../shared/InfiniteScroll';
17
+ import { useThemeProps } from '@mui/system';
18
+ import HiddenPlaceholder from '../../shared/HiddenPlaceholder';
19
+ import { PREFIX } from './constants';
20
+ import User, { UserSkeleton } from '../User';
21
+ import PubSub from 'pubsub-js';
22
+ import { SCEventType, SCTopicType } from '../../constants/PubSub';
23
+ const classes = {
24
+ root: `${PREFIX}-root`,
25
+ title: `${PREFIX}-title`,
26
+ noResults: `${PREFIX}-no-results`,
27
+ showMore: `${PREFIX}-show-more`,
28
+ dialogRoot: `${PREFIX}-dialog-root`,
29
+ endMessage: `${PREFIX}-end-message`
30
+ };
31
+ const Root = styled(Widget, {
32
+ name: PREFIX,
33
+ slot: 'Root'
34
+ })(() => ({}));
35
+ const DialogRoot = styled(BaseDialog, {
36
+ name: PREFIX,
37
+ slot: 'DialogRoot'
38
+ })(() => ({}));
39
+ /**
40
+ * > API documentation for the Community-JS Group Invited Widget component. Learn about the available props and the CSS API.
41
+ *
42
+ *
43
+ * This component renders the list of users who have been invited to join the specified group.
44
+
45
+ #### Import
46
+
47
+ ```jsx
48
+ import {GroupInvitedWidget} from '@selfcommunity/react-ui';
49
+ ```
50
+
51
+ #### Component Name
52
+
53
+ The name `SCGroupInvitedWidget` can be used when providing style overrides in the theme.
54
+
55
+
56
+ #### CSS
57
+
58
+ |Rule Name|Global class|Description|
59
+ |---|---|---|
60
+ |root|.SCGroupInvitedWidget-root|Styles applied to the root element.|
61
+ |title|.SCGroupInvitedWidget-title|Styles applied to the title element.|
62
+ |noResults|.SCGroupInvitedWidget-no-results|Styles applied to no results section.|
63
+ |showMore|.SCGroupInvitedWidget-show-more|Styles applied to show more button element.|
64
+ |dialogRoot|.SCGroupInvitedWidget-dialog-root|Styles applied to the dialog root element.|
65
+ |endMessage|.SCGroupInvitedWidget-end-message|Styles applied to the end message element.|
66
+
67
+ * @param inProps
68
+ */
69
+ export default function GroupInvitedWidget(inProps) {
70
+ var _a, _b;
71
+ // PROPS
72
+ const props = useThemeProps({
73
+ props: inProps,
74
+ name: PREFIX
75
+ });
76
+ const { groupId, group, limit = 5, className, cacheStrategy = CacheStrategies.NETWORK_ONLY, onHeightChange, onStateChange, UserProps = {}, DialogProps = {} } = props, rest = __rest(props, ["groupId", "group", "limit", "className", "cacheStrategy", "onHeightChange", "onStateChange", "UserProps", "DialogProps"]);
77
+ // STATE
78
+ const [state, dispatch] = useReducer(dataWidgetReducer, {
79
+ isLoadingNext: false,
80
+ next: null,
81
+ cacheKey: SCCache.getWidgetStateCacheKey(SCCache.GROUP_REQUESTS_TOOLS_STATE_CACHE_PREFIX_KEY, isInteger(groupId) ? groupId : group.id),
82
+ cacheStrategy,
83
+ visibleItems: limit
84
+ }, stateWidgetInitializer);
85
+ const [openDialog, setOpenDialog] = useState(false);
86
+ // CONTEXT
87
+ const scUserContext = useSCUser();
88
+ const scPreferencesContext = useSCPreferences();
89
+ const { scGroup } = useSCFetchGroup({ id: groupId, group });
90
+ // MEMO
91
+ const contentAvailability = useMemo(() => SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY in scPreferencesContext.preferences &&
92
+ scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY].value, [scPreferencesContext.preferences]);
93
+ // HOOKS
94
+ const theme = useTheme();
95
+ const isMobile = useMediaQuery(theme.breakpoints.down('md'));
96
+ 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]);
97
+ // REFS
98
+ const updatesSubscription = useRef(null);
99
+ /**
100
+ * Initialize component
101
+ * Fetch data only if the component is not initialized and it is not loading data
102
+ */
103
+ const _initComponent = useMemo(() => () => {
104
+ if (!state.initialized && !state.isLoadingNext) {
105
+ dispatch({ type: actionWidgetTypes.LOADING_NEXT });
106
+ GroupService.getGroupInvitedUsers(scGroup.id, { limit })
107
+ .then((payload) => {
108
+ dispatch({ type: actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: Object.assign(Object.assign({}, payload), { initialized: true }) });
109
+ })
110
+ .catch((error) => {
111
+ dispatch({ type: actionWidgetTypes.LOAD_NEXT_FAILURE, payload: { errorLoadNext: error } });
112
+ Logger.error(SCOPE_SC_UI, error);
113
+ });
114
+ }
115
+ }, [state.isLoadingNext, state.initialized, scGroup, limit, dispatch]);
116
+ // EFFECTS
117
+ useEffect(() => {
118
+ var _a;
119
+ let _t;
120
+ if ((contentAvailability || (!contentAvailability && ((_a = scUserContext.user) === null || _a === void 0 ? void 0 : _a.id))) && scGroup && scUserContext.user !== undefined) {
121
+ _t = setTimeout(_initComponent);
122
+ return () => {
123
+ _t && clearTimeout(_t);
124
+ };
125
+ }
126
+ }, [scUserContext.user, contentAvailability, scGroup]);
127
+ useEffect(() => {
128
+ if (openDialog && state.next && state.results.length === limit && state.initialized) {
129
+ dispatch({ type: actionWidgetTypes.LOADING_NEXT });
130
+ GroupService.getGroupInvitedUsers(scGroup.id, { offset: limit, limit: 10 })
131
+ .then((payload) => {
132
+ dispatch({ type: actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: payload });
133
+ })
134
+ .catch((error) => {
135
+ dispatch({ type: actionWidgetTypes.LOAD_NEXT_FAILURE, payload: { errorLoadNext: error } });
136
+ Logger.error(SCOPE_SC_UI, error);
137
+ });
138
+ }
139
+ }, [openDialog, state.next, state.results.length, state.initialized, limit]);
140
+ /**
141
+ * Virtual feed update
142
+ */
143
+ useEffect(() => {
144
+ onHeightChange && onHeightChange();
145
+ }, [state.results]);
146
+ useEffect(() => {
147
+ if (!scGroup || (!contentAvailability && !scUserContext.user)) {
148
+ return;
149
+ }
150
+ else if (cacheStrategy === CacheStrategies.NETWORK_ONLY) {
151
+ onStateChange && onStateChange({ cacheStrategy: CacheStrategies.CACHE_FIRST });
152
+ }
153
+ }, [scUserContext.user, scGroup, contentAvailability]);
154
+ useEffect(() => {
155
+ if (!scGroup || !scUserContext.user || !state.initialized) {
156
+ return;
157
+ }
158
+ }, []);
159
+ /**
160
+ * Subscriber for pubsub callback
161
+ */
162
+ const onChangeGroupHandler = useCallback((_msg, newInvited) => {
163
+ dispatch({
164
+ type: actionWidgetTypes.SET_RESULTS,
165
+ payload: { results: [...state.results, ...newInvited], count: state.count + newInvited.length }
166
+ });
167
+ }, [scGroup, dispatch, state.results]);
168
+ /**
169
+ * On mount, subscribe to receive groups updates (only edit)
170
+ */
171
+ useEffect(() => {
172
+ if (scGroup && state.results) {
173
+ updatesSubscription.current = PubSub.subscribe(`${SCTopicType.GROUP}.${SCEventType.INVITE_MEMBER}`, onChangeGroupHandler);
174
+ }
175
+ return () => {
176
+ updatesSubscription.current && PubSub.unsubscribe(updatesSubscription.current);
177
+ };
178
+ }, [scGroup, state.results]);
179
+ // HANDLERS
180
+ const handleNext = useMemo(() => () => {
181
+ dispatch({ type: actionWidgetTypes.LOADING_NEXT });
182
+ http
183
+ .request({
184
+ url: state.next,
185
+ method: Endpoints.getGroupInvitedUsers.method
186
+ })
187
+ .then((res) => {
188
+ dispatch({ type: actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: res.data });
189
+ });
190
+ }, [dispatch, state.next, state.isLoadingNext, state.initialized]);
191
+ const handleToggleDialogOpen = () => {
192
+ setOpenDialog((prev) => !prev);
193
+ };
194
+ // RENDER
195
+ if ((!state.count && state.initialized) || !contentAvailability || !scGroup || !state.count || !state.results.length || !isGroupAdmin) {
196
+ return React.createElement(HiddenPlaceholder, null);
197
+ }
198
+ if (!state.initialized) {
199
+ return React.createElement(Skeleton, null);
200
+ }
201
+ const content = (React.createElement(CardContent, null,
202
+ React.createElement(Typography, { className: classes.title, variant: "h5" },
203
+ React.createElement(FormattedMessage, { id: "ui.groupInvitedWidget.title", defaultMessage: "ui.groupInvitedWidget.title" })),
204
+ React.createElement(React.Fragment, null,
205
+ React.createElement(List, null, state.results.slice(0, state.visibleItems).map((user) => (React.createElement(ListItem, { key: user.id },
206
+ React.createElement(User, { elevation: 0, actions: React.createElement(Button, { disabled: true, size: "small" },
207
+ React.createElement(FormattedMessage, { id: "ui.groupInvitedWidget.status", defaultMessage: "ui.groupInvitedWidget.status" })), user: user, userId: user.id }))))),
208
+ state.count > state.visibleItems && (React.createElement(Button, { className: classes.showMore, onClick: handleToggleDialogOpen },
209
+ React.createElement(FormattedMessage, { id: "ui.groupInvitedWidget.button.showMore", defaultMessage: "ui.groupInvitedWidget.button.showMore" })))),
210
+ openDialog && (React.createElement(DialogRoot, Object.assign({ className: classes.dialogRoot, title: React.createElement(FormattedMessage, { defaultMessage: "ui.groupInvitedWidget.dialogTitle", id: "ui.groupInvitedWidget.dialogTitle", values: { total: (_b = state === null || state === void 0 ? void 0 : state.results) === null || _b === void 0 ? void 0 : _b.length } }), onClose: handleToggleDialogOpen, open: openDialog }, DialogProps),
211
+ React.createElement(InfiniteScroll, { dataLength: state.results.length, next: handleNext, hasMoreNext: Boolean(state.next), loaderNext: React.createElement(UserSkeleton, Object.assign({ elevation: 0 }, UserProps)), height: isMobile ? '100%' : 400, endMessage: React.createElement(Typography, { className: classes.endMessage },
212
+ React.createElement(FormattedMessage, { id: "ui.groupInvitedWidget.noMoreResults", defaultMessage: "ui.groupInvitedWidget.noMoreResults" })) },
213
+ React.createElement(List, null, state.results.map((user) => (React.createElement(ListItem, { key: user.id },
214
+ React.createElement(User, { elevation: 0, actions: React.createElement(Button, { disabled: true, size: "small" },
215
+ React.createElement(FormattedMessage, { id: "ui.groupInvitedWidget.status", defaultMessage: "ui.groupInvitedWidget.status" })), user: user, userId: user.id }))))))))));
216
+ return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest), content));
217
+ }
@@ -0,0 +1,22 @@
1
+ import { WidgetProps } from '../Widget';
2
+ /**
3
+ * > API documentation for the Community-JS Group Invited Widget Skeleton component. Learn about the available props and the CSS API.
4
+
5
+ #### Import
6
+
7
+ ```jsx
8
+ import {GroupInvitedWidgetSkeleton} from '@selfcommunity/react-ui';
9
+ ```
10
+
11
+ #### Component Name
12
+
13
+ The name `SCGroupInvitedWidget-skeleton-root` can be used when providing style overrides in the theme.
14
+
15
+ #### CSS
16
+
17
+ |Rule Name|Global class|Description|
18
+ |---|---|---|
19
+ |root|.SCGroupInvitedWidget-skeleton-root|Styles applied to the root element.|
20
+ *
21
+ */
22
+ export default function GroupInvitedWidgetSkeleton(props: WidgetProps): JSX.Element;
@@ -0,0 +1,34 @@
1
+ import React from 'react';
2
+ import { CategoryTrendingPeopleWidgetSkeleton } from '../CategoryTrendingUsersWidget';
3
+ import { styled } from '@mui/material/styles';
4
+ import { PREFIX } from './constants';
5
+ const classes = {
6
+ root: `${PREFIX}-skeleton-root`
7
+ };
8
+ const Root = styled(CategoryTrendingPeopleWidgetSkeleton, {
9
+ name: PREFIX,
10
+ slot: 'SkeletonRoot'
11
+ })(() => ({}));
12
+ /**
13
+ * > API documentation for the Community-JS Group Invited Widget Skeleton component. Learn about the available props and the CSS API.
14
+
15
+ #### Import
16
+
17
+ ```jsx
18
+ import {GroupInvitedWidgetSkeleton} from '@selfcommunity/react-ui';
19
+ ```
20
+
21
+ #### Component Name
22
+
23
+ The name `SCGroupInvitedWidget-skeleton-root` can be used when providing style overrides in the theme.
24
+
25
+ #### CSS
26
+
27
+ |Rule Name|Global class|Description|
28
+ |---|---|---|
29
+ |root|.SCGroupInvitedWidget-skeleton-root|Styles applied to the root element.|
30
+ *
31
+ */
32
+ export default function GroupInvitedWidgetSkeleton(props) {
33
+ return React.createElement(Root, Object.assign({ className: classes.root }, props));
34
+ }
@@ -0,0 +1 @@
1
+ export declare const PREFIX = "SCGroupInvitedWidget";
@@ -0,0 +1 @@
1
+ export const PREFIX = 'SCGroupInvitedWidget';
@@ -0,0 +1,4 @@
1
+ import GroupInvitedWidget, { GroupInvitedWidgetProps } from './GroupInvitedWidget';
2
+ import GroupInvitedWidgetSkeleton from './Skeleton';
3
+ export default GroupInvitedWidget;
4
+ export { GroupInvitedWidgetProps, GroupInvitedWidgetSkeleton };
@@ -0,0 +1,4 @@
1
+ import GroupInvitedWidget from './GroupInvitedWidget';
2
+ import GroupInvitedWidgetSkeleton from './Skeleton';
3
+ export default GroupInvitedWidget;
4
+ export { GroupInvitedWidgetSkeleton };
@@ -8,7 +8,7 @@ import InfiniteScroll from '../../shared/InfiniteScroll';
8
8
  import User, { UserSkeleton } from '../User';
9
9
  import { Endpoints, GroupService, http } from '@selfcommunity/api-services';
10
10
  import { useSCFetchGroup } from '@selfcommunity/react-core';
11
- import { SCGroupPrivacyType } from '@selfcommunity/types';
11
+ import { SCGroupPrivacyType, SCGroupSubscriptionStatusType } from '@selfcommunity/types';
12
12
  import AvatarGroupSkeleton from '../Skeleton/AvatarGroupSkeleton';
13
13
  import classNames from 'classnames';
14
14
  import { useThemeProps } from '@mui/system';
@@ -70,7 +70,11 @@ export default function GroupMembersButton(inProps) {
70
70
  const { scGroup } = useSCFetchGroup({ id: groupId, group });
71
71
  // FETCH FIRST FOLLOWERS
72
72
  useDeepCompareEffectNoCheck(() => {
73
- if (!scGroup || (scGroup && scGroup.privacy !== SCGroupPrivacyType.PUBLIC && autoHide)) {
73
+ if (!scGroup ||
74
+ (scGroup &&
75
+ scGroup.privacy !== SCGroupPrivacyType.PUBLIC &&
76
+ scGroup.subscription_status !== SCGroupSubscriptionStatusType.SUBSCRIBED &&
77
+ autoHide)) {
74
78
  return;
75
79
  }
76
80
  if (members.length === 0) {
@@ -129,5 +133,5 @@ export default function GroupMembersButton(inProps) {
129
133
  React.createElement(InfiniteScroll, { dataLength: members.length, next: fetchMembers, hasMoreNext: next !== null || loading, loaderNext: React.createElement(UserSkeleton, { elevation: 0 }), height: isMobile ? '100%' : 400, endMessage: React.createElement(Typography, { className: classes.endMessage },
130
134
  React.createElement(FormattedMessage, { id: "ui.groupMembersButton.noOtherMembers", defaultMessage: "ui.groupMembersButton.noOtherMembers" })) },
131
135
  React.createElement(List, null, members.map((member) => (React.createElement(ListItem, { key: member.id },
132
- React.createElement(User, { elevation: 0, user: member }))))))))));
136
+ React.createElement(User, { elevation: 0, user: member, onClick: handleToggleDialogOpen }))))))))));
133
137
  }
@@ -6,7 +6,7 @@ import { Button, CardActions, CardContent, ListItem, Typography, useMediaQuery,
6
6
  import Widget from '../Widget';
7
7
  import { http, Endpoints, GroupService } from '@selfcommunity/api-services';
8
8
  import { CacheStrategies, isInteger, Logger } from '@selfcommunity/utils';
9
- import { SCCache, SCPreferences, useSCFetchGroup, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
9
+ import { Link, SCCache, SCPreferences, SCRoutes, useSCFetchGroup, useSCPreferences, useSCRouting, useSCUser } from '@selfcommunity/react-core';
10
10
  import { actionWidgetTypes, dataWidgetReducer, stateWidgetInitializer } from '../../utils/widget';
11
11
  import Skeleton from './Skeleton';
12
12
  import { FormattedMessage } from 'react-intl';
@@ -87,6 +87,7 @@ export default function GroupMembersWidget(inProps) {
87
87
  const [openDialog, setOpenDialog] = useState(false);
88
88
  // CONTEXT
89
89
  const scUserContext = useSCUser();
90
+ const scRoutingContext = useSCRouting();
90
91
  const scPreferencesContext = useSCPreferences();
91
92
  const { scGroup } = useSCFetchGroup({ id: groupId, group });
92
93
  // CONST
@@ -172,6 +173,14 @@ export default function GroupMembersWidget(inProps) {
172
173
  const handleToggleDialogOpen = () => {
173
174
  setOpenDialog((prev) => !prev);
174
175
  };
176
+ const handleRefresh = useMemo(() => (userId) => {
177
+ const newMembers = [...state.results];
178
+ const _updated = newMembers.filter((u) => u.id !== userId);
179
+ dispatch({
180
+ type: actionWidgetTypes.SET_RESULTS,
181
+ payload: { results: newMembers.length > 1 ? _updated : [] }
182
+ });
183
+ }, [dispatch, state.count, state.results]);
175
184
  // RENDER
176
185
  if ((autoHide && !state.count && state.initialized) || (!contentAvailability && !scUserContext.user) || !scGroup) {
177
186
  return React.createElement(HiddenPlaceholder, null);
@@ -185,17 +194,23 @@ export default function GroupMembersWidget(inProps) {
185
194
  React.createElement(FormattedMessage, { id: "ui.groupMembersWidget.title", defaultMessage: "ui.groupMembersWidget.title" })),
186
195
  !state.count ? (React.createElement(Typography, { className: classes.noResults, variant: "body2" },
187
196
  React.createElement(FormattedMessage, { id: "ui.groupMembersWidget.subtitle.noResults", defaultMessage: "" }))) : (React.createElement(React.Fragment, null,
188
- React.createElement(List, null, state.results.slice(0, state.visibleItems).map((user) => (React.createElement(ListItem, { key: user.id },
189
- React.createElement(User, { elevation: 0, actions: isGroupAdmin ? (React.createElement(GroupSettingsIconButton, { group: scGroup, user: user })) : (React.createElement(Button, null,
190
- React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" }))), user: user, userId: user.id }))))),
197
+ React.createElement(List, null, state.results.slice(0, state.visibleItems).map((user) => {
198
+ var _a, _b;
199
+ return (React.createElement(ListItem, { key: user.id },
200
+ React.createElement(User, { elevation: 0, actions: isGroupAdmin ? (React.createElement(GroupSettingsIconButton, { group: scGroup, user: user, onRemoveSuccess: () => handleRefresh(user.id) })) : ((_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.id) !== user.id ? (React.createElement(Button, { size: "small", variant: "outlined", component: Link, to: scRoutingContext.url(SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user) },
201
+ React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" }))) : null, isGroupAdmin: ((_b = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _b === void 0 ? void 0 : _b.id) === user.id, user: user, userId: user.id })));
202
+ })),
191
203
  state.count > state.visibleItems && (React.createElement(Button, { className: classes.showMore, onClick: handleToggleDialogOpen },
192
204
  React.createElement(FormattedMessage, { id: "ui.groupMembersWidget.button.showMore", defaultMessage: "ui.groupMembersWidget.button.showMore" }))))),
193
205
  openDialog && (React.createElement(DialogRoot, Object.assign({ className: classes.dialogRoot, title: React.createElement(FormattedMessage, { defaultMessage: "ui.groupMembersWidget.dialogTitle", id: "ui.groupMembersWidget.dialogTitle", values: { total: scGroup.subscribers_counter } }), onClose: handleToggleDialogOpen, open: openDialog }, DialogProps),
194
206
  React.createElement(InfiniteScroll, { dataLength: state.results.length, next: handleNext, hasMoreNext: Boolean(state.next), loaderNext: React.createElement(UserSkeleton, Object.assign({ elevation: 0 }, UserProps)), height: isMobile ? '100%' : 400, endMessage: React.createElement(Typography, { className: classes.endMessage },
195
207
  React.createElement(FormattedMessage, { id: "ui.groupMembersWidget.noMoreResults", defaultMessage: "ui.groupMembersWidget.noMoreResults" })) },
196
- React.createElement(List, null, state.results.map((user) => (React.createElement(ListItem, { key: user.id },
197
- React.createElement(User, { elevation: 0, actions: isGroupAdmin ? (React.createElement(GroupSettingsIconButton, { group: scGroup, user: user })) : (React.createElement(Button, null,
198
- React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" }))), user: user, userId: user.id }))))))))),
208
+ React.createElement(List, null, state.results.map((user) => {
209
+ var _a, _b;
210
+ return (React.createElement(ListItem, { key: user.id },
211
+ React.createElement(User, { elevation: 0, actions: isGroupAdmin ? (React.createElement(GroupSettingsIconButton, { group: scGroup, user: user, onRemoveSuccess: () => handleRefresh(user.id) })) : ((_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.id) !== user.id ? (React.createElement(Button, { size: "small", variant: "outlined", component: Link, to: scRoutingContext.url(SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user) },
212
+ React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" }))) : null, isGroupAdmin: ((_b = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _b === void 0 ? void 0 : _b.id) === user.id, user: user, userId: user.id })));
213
+ })))))),
199
214
  React.createElement(CardActions, { className: classes.actions },
200
215
  React.createElement(GroupInviteButton, { groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, group: scGroup }))));
201
216
  return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest), content));
@@ -4,6 +4,7 @@ import { CacheStrategies } from '@selfcommunity/utils';
4
4
  import { BaseDialogProps } from '../../shared/BaseDialog';
5
5
  import { VirtualScrollerItemProps } from '../../types/virtualScroller';
6
6
  import { UserProps } from '../User';
7
+ import { GroupSubscribeButtonProps } from '../GroupSubscribeButton';
7
8
  export interface GroupRequestsWidgetProps extends VirtualScrollerItemProps, WidgetProps {
8
9
  /**
9
10
  * Group Object
@@ -35,6 +36,16 @@ export interface GroupRequestsWidgetProps extends VirtualScrollerItemProps, Widg
35
36
  * @default {}
36
37
  */
37
38
  DialogProps?: BaseDialogProps;
39
+ /**
40
+ * Props to spread to group subscribe button component
41
+ * @default {}
42
+ */
43
+ GroupSubscribeButtonProps?: GroupSubscribeButtonProps;
44
+ /**
45
+ * onSubscribeAction callback
46
+ * @param user
47
+ */
48
+ onSubscribeActon?: (userId: number | string) => any;
38
49
  /**
39
50
  * Other props
40
51
  */
@@ -44,8 +55,7 @@ export interface GroupRequestsWidgetProps extends VirtualScrollerItemProps, Widg
44
55
  * > API documentation for the Community-JS Group Requests Widget component. Learn about the available props and the CSS API.
45
56
  *
46
57
  *
47
- * This component renders the list of the follows of the given group.
48
- * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/GroupRequests)
58
+ * This component displays the list of users who have requested access to the specified group.
49
59
 
50
60
  #### Import
51
61
 
@@ -39,8 +39,7 @@ const DialogRoot = styled(BaseDialog, {
39
39
  * > API documentation for the Community-JS Group Requests Widget component. Learn about the available props and the CSS API.
40
40
  *
41
41
  *
42
- * This component renders the list of the follows of the given group.
43
- * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/GroupRequests)
42
+ * This component displays the list of users who have requested access to the specified group.
44
43
 
45
44
  #### Import
46
45
 
@@ -73,7 +72,7 @@ export default function GroupRequestsWidget(inProps) {
73
72
  props: inProps,
74
73
  name: PREFIX
75
74
  });
76
- const { groupId, group, limit = 5, className, cacheStrategy = CacheStrategies.NETWORK_ONLY, onHeightChange, onStateChange, UserProps = {}, DialogProps = {} } = props, rest = __rest(props, ["groupId", "group", "limit", "className", "cacheStrategy", "onHeightChange", "onStateChange", "UserProps", "DialogProps"]);
75
+ const { groupId, group, limit = 5, className, cacheStrategy = CacheStrategies.NETWORK_ONLY, onHeightChange, onStateChange, UserProps = {}, DialogProps = {}, GroupSubscribeButtonProps = {}, onSubscribeActon } = props, rest = __rest(props, ["groupId", "group", "limit", "className", "cacheStrategy", "onHeightChange", "onStateChange", "UserProps", "DialogProps", "GroupSubscribeButtonProps", "onSubscribeActon"]);
77
76
  // STATE
78
77
  const [state, dispatch] = useReducer(dataWidgetReducer, {
79
78
  isLoadingNext: false,
@@ -169,15 +168,17 @@ export default function GroupRequestsWidget(inProps) {
169
168
  const handleToggleDialogOpen = () => {
170
169
  setOpenDialog((prev) => !prev);
171
170
  };
172
- const handleSubscribeAction = useMemo(() => (userId) => {
171
+ const handleSubscribeAction = useMemo(() => (user) => {
173
172
  const newRequests = [...state.results];
174
- const index = newRequests.findIndex((u) => u.id === userId);
175
- if (index !== -1) {
176
- dispatch({ type: actionWidgetTypes.SET_RESULTS, payload: { results: newRequests } });
177
- }
178
- }, [dispatch, state.count, state.results]);
173
+ const _updated = newRequests.filter((u) => u.id !== user.id);
174
+ dispatch({
175
+ type: actionWidgetTypes.SET_RESULTS,
176
+ payload: { results: newRequests.length > 1 ? _updated : [] }
177
+ });
178
+ onSubscribeActon && onSubscribeActon(user);
179
+ }, [dispatch, state.count, state.results, onSubscribeActon]);
179
180
  // RENDER
180
- if ((!state.count && state.initialized) || (!contentAvailability && !isGroupAdmin) || !scGroup || !state.count) {
181
+ if ((!state.count && state.initialized) || !contentAvailability || !scGroup || !state.count || !state.results.length || !isGroupAdmin) {
181
182
  return React.createElement(HiddenPlaceholder, null);
182
183
  }
183
184
  if (!state.initialized) {
@@ -188,13 +189,13 @@ export default function GroupRequestsWidget(inProps) {
188
189
  React.createElement(FormattedMessage, { id: "ui.groupRequestsWidget.title", defaultMessage: "ui.groupRequestsWidget.title" })),
189
190
  React.createElement(React.Fragment, null,
190
191
  React.createElement(List, null, state.results.slice(0, state.visibleItems).map((user) => (React.createElement(ListItem, { key: user.id },
191
- React.createElement(User, { elevation: 0, actions: React.createElement(GroupSubscribeButton, { group: scGroup, groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, userId: user.id, onSubscribe: () => handleSubscribeAction(user.id) }), user: user, userId: user.id }))))),
192
+ React.createElement(User, { elevation: 0, actions: React.createElement(GroupSubscribeButton, Object.assign({ group: scGroup, groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, user: user, onSubscribe: () => handleSubscribeAction(user) }, GroupSubscribeButtonProps)), user: user, userId: user.id }))))),
192
193
  state.count > state.visibleItems && (React.createElement(Button, { className: classes.showMore, onClick: handleToggleDialogOpen },
193
194
  React.createElement(FormattedMessage, { id: "ui.groupRequestsWidget.button.showMore", defaultMessage: "ui.groupRequestsWidget.button.showMore" })))),
194
195
  openDialog && (React.createElement(DialogRoot, Object.assign({ className: classes.dialogRoot, title: React.createElement(FormattedMessage, { defaultMessage: "ui.groupRequestsWidget.dialogTitle", id: "ui.groupRequestsWidget.dialogTitle", values: { total: scGroup.subscribers_counter } }), onClose: handleToggleDialogOpen, open: openDialog }, DialogProps),
195
196
  React.createElement(InfiniteScroll, { dataLength: state.results.length, next: handleNext, hasMoreNext: Boolean(state.next), loaderNext: React.createElement(UserSkeleton, Object.assign({ elevation: 0 }, UserProps)), height: isMobile ? '100%' : 400, endMessage: React.createElement(Typography, { className: classes.endMessage },
196
197
  React.createElement(FormattedMessage, { id: "ui.groupRequestsWidget.noMoreResults", defaultMessage: "ui.groupRequestsWidget.noMoreResults" })) },
197
198
  React.createElement(List, null, state.results.map((user) => (React.createElement(ListItem, { key: user.id },
198
- React.createElement(User, { elevation: 0, actions: React.createElement(GroupSubscribeButton, { group: scGroup, groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, userId: user.id }), user: user, userId: user.id }))))))))));
199
+ React.createElement(User, { elevation: 0, actions: React.createElement(GroupSubscribeButton, Object.assign({ group: scGroup, groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, user: user, onSubscribe: () => handleSubscribeAction(user) }, GroupSubscribeButtonProps)), user: user, userId: user.id }))))))))));
199
200
  return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest), content));
200
201
  }
@@ -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
  */
@@ -8,6 +8,9 @@ import classNames from 'classnames';
8
8
  import { useThemeProps } from '@mui/system';
9
9
  import { Link, SCRoutes, useSCRouting, useSCUser } from '@selfcommunity/react-core';
10
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';
11
14
  const PREFIX = 'SCGroupSettingsIconButton';
12
15
  const classes = {
13
16
  root: `${PREFIX}-root`,
@@ -56,7 +59,7 @@ export default function GroupSettingsIconButton(inProps) {
56
59
  props: inProps,
57
60
  name: PREFIX
58
61
  });
59
- const { className = null, onMenuItemRemoveClick, group, user, onItemRemoveConfirm, userToRemove } = props, rest = __rest(props, ["className", "onMenuItemRemoveClick", "group", "user", "onItemRemoveConfirm", "userToRemove"]);
62
+ const { className = null, group, user, onRemoveSuccess } = props, rest = __rest(props, ["className", "group", "user", "onRemoveSuccess"]);
60
63
  // STATE
61
64
  const [anchorEl, setAnchorEl] = useState(null);
62
65
  const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
@@ -80,22 +83,31 @@ export default function GroupSettingsIconButton(inProps) {
80
83
  const handleCloseDialog = () => {
81
84
  setOpenConfirmDialog(false);
82
85
  setAnchorEl(null);
83
- onItemRemoveConfirm && onItemRemoveConfirm();
84
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
+ }
85
97
  /**
86
98
  * Handles thread deletion
87
99
  */
88
100
  function handleRemoveUser() {
89
- console.log(userToRemove);
90
- // GroupService.removeUserFromGroup(group.id, userToRemove)
91
- // .then(() => {
92
- // PubSub.publish('snippetsChannelDelete', userToRemove);
93
- // handleCloseDialog();
94
- // })
95
- // .catch((error) => {
96
- // setOpenConfirmDialog(false);
97
- // console.log(error);
98
- // });
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
+ });
99
111
  }
100
112
  if (scUserContext.user.id === user.id) {
101
113
  return null;
@@ -108,9 +120,7 @@ export default function GroupSettingsIconButton(inProps) {
108
120
  return [
109
121
  React.createElement(ListItem, { className: classes.item, key: "message", component: Link, to: scRoutingContext.url(SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user) },
110
122
  React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" })),
111
- React.createElement(ListItem, { className: classes.item, key: "report", onClick: () => console.log('report') },
112
- React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.report", defaultMessage: "ui.groupSettingsIconButton.item.report" })),
113
- React.createElement(ListItem, { className: classes.item, key: "delete", onClick: userToRemove ? handleOpenDialog : onMenuItemRemoveClick },
123
+ React.createElement(ListItem, { className: classes.item, key: "delete", onClick: handleOpenDialog },
114
124
  React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.remove", defaultMessage: "ui.groupSettingsIconButton.item.remove" }))
115
125
  ];
116
126
  }
@@ -118,9 +128,7 @@ export default function GroupSettingsIconButton(inProps) {
118
128
  return [
119
129
  React.createElement(MenuItem, { className: classes.item, component: Link, to: scRoutingContext.url(SCRoutes.USER_PRIVATE_MESSAGES_ROUTE_NAME, user), key: "message" },
120
130
  React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.message", defaultMessage: "ui.groupSettingsIconButton.item.message" })),
121
- React.createElement(MenuItem, { className: classes.item, onClick: () => console.log('report'), key: "report" },
122
- React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.report", defaultMessage: "ui.groupSettingsIconButton.item.report" })),
123
- React.createElement(MenuItem, { className: classes.item, onClick: userToRemove ? handleOpenDialog : onMenuItemRemoveClick, key: "delete" },
131
+ React.createElement(MenuItem, { className: classes.item, onClick: handleOpenDialog, key: "delete" },
124
132
  React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.item.remove", defaultMessage: "ui.groupSettingsIconButton.item.remove" }))
125
133
  ];
126
134
  }
@@ -130,5 +138,11 @@ export default function GroupSettingsIconButton(inProps) {
130
138
  React.createElement(Icon, null, "more_vert")),
131
139
  isMobile ? (React.createElement(SwipeableDrawerRoot, { className: classes.drawerRoot, anchor: "bottom", open: Boolean(anchorEl), onClose: handleClose, onOpen: handleOpen, PaperProps: { className: classes.paper }, disableSwipeToOpen: true },
132
140
  React.createElement(List, null, renderList()))) : (React.createElement(MenuRoot, { className: classes.menuRoot, anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, PaperProps: { className: classes.paper } }, renderList())),
133
- openConfirmDialog && (React.createElement(ConfirmDialog, { open: openConfirmDialog, title: React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.dialog.msg", defaultMessage: "ui.groupSettingsIconButton.dialog.msg" }), btnConfirm: React.createElement(FormattedMessage, { id: "ui.groupSettingsIconButton.dialog.confirm", defaultMessage: "ui.groupSettingsIconButton.dialog.confirm" }), onConfirm: handleRemoveUser, onClose: handleCloseDialog }))));
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 }))));
134
148
  }
@@ -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