@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.
- package/lib/cjs/components/AccountRecover/AccountRecover.js +6 -1
- package/lib/cjs/components/BottomNavigation/BottomNavigation.js +4 -3
- package/lib/cjs/components/CategoryHeader/Skeleton.js +3 -2
- package/lib/cjs/components/ChangeGroupCover/ChangeGroupCover.js +6 -6
- package/lib/cjs/components/ChangeGroupPicture/ChangeGroupPicture.js +19 -16
- package/lib/cjs/components/Composer/Attributes/Attributes.js +3 -3
- package/lib/cjs/components/Composer/Composer.js +3 -3
- package/lib/cjs/components/Composer/Layer/AudienceLayer/AudienceLayer.d.ts +1 -1
- package/lib/cjs/components/Composer/Layer/AudienceLayer/AudienceLayer.js +9 -19
- package/lib/cjs/components/Editor/Editor.js +2 -0
- package/lib/cjs/components/Editor/nodes/ImageNode.js +6 -0
- package/lib/cjs/components/Editor/plugins/ImagePlugin.js +4 -0
- package/lib/cjs/components/Editor/plugins/ToolbarPlugin.js +17 -3
- package/lib/cjs/components/FeedObject/Actions/Share/Share.js +18 -16
- package/lib/cjs/components/FeedObject/Contributors/Contributors.js +1 -1
- package/lib/cjs/components/FeedObject/FeedObject.d.ts +1 -0
- package/lib/cjs/components/FeedObject/FeedObject.js +27 -8
- package/lib/cjs/components/FeedObject/Poll/Poll.js +20 -20
- package/lib/cjs/components/FeedUpdatesWidget/FeedUpdatesWidget.js +1 -1
- package/lib/cjs/components/Footer/Footer.js +1 -1
- package/lib/cjs/components/Group/Group.d.ts +9 -1
- package/lib/cjs/components/Group/Group.js +18 -6
- package/lib/cjs/components/GroupAutocomplete/GroupAutocomplete.d.ts +0 -1
- package/lib/cjs/components/GroupAutocomplete/GroupAutocomplete.js +1 -2
- package/lib/cjs/components/GroupForm/GroupForm.js +64 -13
- package/lib/cjs/components/GroupHeader/GroupHeader.d.ts +2 -3
- package/lib/cjs/components/GroupHeader/GroupHeader.js +38 -5
- package/lib/cjs/components/GroupInfoWidget/GroupInfoWidget.js +65 -9
- package/lib/cjs/components/GroupInviteButton/GroupInviteButton.js +29 -7
- package/lib/cjs/components/GroupInvitedWidget/GroupInvitedWidget.d.ts +73 -0
- package/lib/cjs/components/GroupInvitedWidget/GroupInvitedWidget.js +220 -0
- package/lib/cjs/components/GroupInvitedWidget/Skeleton.d.ts +22 -0
- package/lib/cjs/components/GroupInvitedWidget/Skeleton.js +38 -0
- package/lib/cjs/components/GroupInvitedWidget/constants.d.ts +1 -0
- package/lib/cjs/components/GroupInvitedWidget/constants.js +4 -0
- package/lib/cjs/components/GroupInvitedWidget/index.d.ts +4 -0
- package/lib/cjs/components/GroupInvitedWidget/index.js +8 -0
- package/lib/cjs/components/GroupMembersButton/GroupMembersButton.js +6 -2
- package/lib/cjs/components/GroupMembersWidget/GroupMembersWidget.js +21 -6
- package/lib/cjs/components/GroupRequestsWidget/GroupRequestsWidget.d.ts +12 -2
- package/lib/cjs/components/GroupRequestsWidget/GroupRequestsWidget.js +13 -12
- package/lib/cjs/components/GroupSettingsIconButton/GroupSettingsIconButton.d.ts +4 -12
- package/lib/cjs/components/GroupSettingsIconButton/GroupSettingsIconButton.js +33 -19
- package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.d.ts +3 -3
- package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.js +22 -6
- package/lib/cjs/components/Groups/Groups.d.ts +15 -8
- package/lib/cjs/components/Groups/Groups.js +86 -32
- package/lib/cjs/components/Groups/Skeleton.d.ts +4 -0
- package/lib/cjs/components/Groups/Skeleton.js +2 -2
- package/lib/cjs/components/InlineComposerWidget/InlineComposerWidget.js +7 -0
- package/lib/cjs/components/NavigationSettingsIconButton/NavigationSettingsIconButton.js +4 -4
- package/lib/cjs/components/NavigationToolbar/NavigationToolbar.js +10 -2
- package/lib/cjs/components/NavigationToolbarMobile/NavigationToolbarMobile.d.ts +1 -0
- package/lib/cjs/components/NavigationToolbarMobile/NavigationToolbarMobile.js +9 -1
- package/lib/cjs/components/Notification/Group/Group.d.ts +15 -0
- package/lib/cjs/components/Notification/Group/Group.js +87 -0
- package/lib/cjs/components/Notification/Group/index.d.ts +3 -0
- package/lib/cjs/components/Notification/Group/index.js +5 -0
- package/lib/cjs/components/Notification/Notification.js +34 -1
- package/lib/cjs/components/Notification/PrivateMessage/PrivateMessage.js +16 -5
- package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.d.ts +7 -1
- package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.js +16 -8
- package/lib/cjs/components/PrivateMessageSettingsIconButton/PrivateMessageSettingsIconButton.js +1 -1
- package/lib/cjs/components/PrivateMessageSnippetItem/PrivateMessageSnippetItem.js +11 -6
- package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.d.ts +9 -4
- package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.js +24 -6
- package/lib/cjs/components/PrivateMessageThread/PrivateMessageThread.d.ts +6 -1
- package/lib/cjs/components/PrivateMessageThread/PrivateMessageThread.js +46 -20
- package/lib/cjs/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +6 -0
- package/lib/cjs/components/SearchAutocomplete/SearchAutocomplete.js +22 -5
- package/lib/cjs/components/SnippetNotifications/SnippetNotifications.js +7 -0
- package/lib/cjs/components/ToastNotifications/ToastNotifications.js +7 -0
- package/lib/cjs/components/User/User.d.ts +6 -1
- package/lib/cjs/components/User/User.js +5 -4
- package/lib/cjs/components/UserSubscribedGroupsWidget/Skeleton.d.ts +21 -0
- package/lib/cjs/components/UserSubscribedGroupsWidget/Skeleton.js +46 -0
- package/lib/cjs/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.d.ts +68 -0
- package/lib/cjs/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.js +183 -0
- package/lib/cjs/components/UserSubscribedGroupsWidget/constants.d.ts +1 -0
- package/lib/cjs/components/UserSubscribedGroupsWidget/constants.js +4 -0
- package/lib/cjs/components/UserSubscribedGroupsWidget/index.d.ts +4 -0
- package/lib/cjs/components/UserSubscribedGroupsWidget/index.js +8 -0
- package/lib/cjs/components/VoteAudienceButton/VoteAudienceButton.js +1 -1
- package/lib/cjs/constants/PubSub.d.ts +28 -0
- package/lib/cjs/constants/PubSub.js +22 -0
- package/lib/cjs/index.d.ts +5 -3
- package/lib/cjs/index.js +11 -4
- package/lib/cjs/types/index.d.ts +2 -1
- package/lib/esm/components/AccountRecover/AccountRecover.js +6 -1
- package/lib/esm/components/BottomNavigation/BottomNavigation.js +5 -4
- package/lib/esm/components/CategoryHeader/Skeleton.js +3 -2
- package/lib/esm/components/ChangeGroupCover/ChangeGroupCover.js +6 -6
- package/lib/esm/components/ChangeGroupPicture/ChangeGroupPicture.js +19 -16
- package/lib/esm/components/Composer/Attributes/Attributes.js +3 -3
- package/lib/esm/components/Composer/Composer.js +3 -3
- package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.d.ts +1 -1
- package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.js +9 -19
- package/lib/esm/components/Editor/Editor.js +2 -0
- package/lib/esm/components/Editor/nodes/ImageNode.js +6 -0
- package/lib/esm/components/Editor/plugins/ImagePlugin.js +4 -0
- package/lib/esm/components/Editor/plugins/ToolbarPlugin.js +19 -5
- package/lib/esm/components/FeedObject/Actions/Share/Share.js +19 -17
- package/lib/esm/components/FeedObject/Contributors/Contributors.js +1 -1
- package/lib/esm/components/FeedObject/FeedObject.d.ts +1 -0
- package/lib/esm/components/FeedObject/FeedObject.js +28 -9
- package/lib/esm/components/FeedObject/Poll/Poll.js +20 -20
- package/lib/esm/components/FeedUpdatesWidget/FeedUpdatesWidget.js +1 -1
- package/lib/esm/components/Footer/Footer.js +2 -2
- package/lib/esm/components/Group/Group.d.ts +9 -1
- package/lib/esm/components/Group/Group.js +22 -10
- package/lib/esm/components/GroupAutocomplete/GroupAutocomplete.d.ts +0 -1
- package/lib/esm/components/GroupAutocomplete/GroupAutocomplete.js +1 -2
- package/lib/esm/components/GroupForm/GroupForm.js +64 -13
- package/lib/esm/components/GroupHeader/GroupHeader.d.ts +2 -3
- package/lib/esm/components/GroupHeader/GroupHeader.js +40 -7
- package/lib/esm/components/GroupInfoWidget/GroupInfoWidget.js +65 -9
- package/lib/esm/components/GroupInviteButton/GroupInviteButton.js +29 -7
- package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.d.ts +73 -0
- package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.js +217 -0
- package/lib/esm/components/GroupInvitedWidget/Skeleton.d.ts +22 -0
- package/lib/esm/components/GroupInvitedWidget/Skeleton.js +34 -0
- package/lib/esm/components/GroupInvitedWidget/constants.d.ts +1 -0
- package/lib/esm/components/GroupInvitedWidget/constants.js +1 -0
- package/lib/esm/components/GroupInvitedWidget/index.d.ts +4 -0
- package/lib/esm/components/GroupInvitedWidget/index.js +4 -0
- package/lib/esm/components/GroupMembersButton/GroupMembersButton.js +7 -3
- package/lib/esm/components/GroupMembersWidget/GroupMembersWidget.js +22 -7
- package/lib/esm/components/GroupRequestsWidget/GroupRequestsWidget.d.ts +12 -2
- package/lib/esm/components/GroupRequestsWidget/GroupRequestsWidget.js +13 -12
- package/lib/esm/components/GroupSettingsIconButton/GroupSettingsIconButton.d.ts +4 -12
- package/lib/esm/components/GroupSettingsIconButton/GroupSettingsIconButton.js +33 -19
- package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.d.ts +3 -3
- package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.js +22 -6
- package/lib/esm/components/Groups/Groups.d.ts +15 -8
- package/lib/esm/components/Groups/Groups.js +91 -37
- package/lib/esm/components/Groups/Skeleton.d.ts +4 -0
- package/lib/esm/components/Groups/Skeleton.js +2 -2
- package/lib/esm/components/InlineComposerWidget/InlineComposerWidget.js +9 -2
- package/lib/esm/components/NavigationSettingsIconButton/NavigationSettingsIconButton.js +4 -4
- package/lib/esm/components/NavigationToolbar/NavigationToolbar.js +11 -3
- package/lib/esm/components/NavigationToolbarMobile/NavigationToolbarMobile.d.ts +1 -0
- package/lib/esm/components/NavigationToolbarMobile/NavigationToolbarMobile.js +11 -3
- package/lib/esm/components/Notification/Group/Group.d.ts +15 -0
- package/lib/esm/components/Notification/Group/Group.js +84 -0
- package/lib/esm/components/Notification/Group/index.d.ts +3 -0
- package/lib/esm/components/Notification/Group/index.js +2 -0
- package/lib/esm/components/Notification/Notification.js +34 -1
- package/lib/esm/components/Notification/PrivateMessage/PrivateMessage.js +16 -5
- package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.d.ts +7 -1
- package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.js +17 -9
- package/lib/esm/components/PrivateMessageSettingsIconButton/PrivateMessageSettingsIconButton.js +1 -1
- package/lib/esm/components/PrivateMessageSnippetItem/PrivateMessageSnippetItem.js +11 -6
- package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.d.ts +9 -4
- package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.js +26 -8
- package/lib/esm/components/PrivateMessageThread/PrivateMessageThread.d.ts +6 -1
- package/lib/esm/components/PrivateMessageThread/PrivateMessageThread.js +48 -22
- package/lib/esm/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +7 -1
- package/lib/esm/components/SearchAutocomplete/SearchAutocomplete.js +22 -5
- package/lib/esm/components/SnippetNotifications/SnippetNotifications.js +7 -0
- package/lib/esm/components/ToastNotifications/ToastNotifications.js +7 -0
- package/lib/esm/components/User/User.d.ts +6 -1
- package/lib/esm/components/User/User.js +5 -4
- package/lib/esm/components/UserSubscribedGroupsWidget/Skeleton.d.ts +21 -0
- package/lib/esm/components/UserSubscribedGroupsWidget/Skeleton.js +42 -0
- package/lib/esm/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.d.ts +68 -0
- package/lib/esm/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.js +180 -0
- package/lib/esm/components/UserSubscribedGroupsWidget/constants.d.ts +1 -0
- package/lib/esm/components/UserSubscribedGroupsWidget/constants.js +1 -0
- package/lib/esm/components/UserSubscribedGroupsWidget/index.d.ts +4 -0
- package/lib/esm/components/UserSubscribedGroupsWidget/index.js +4 -0
- package/lib/esm/components/VoteAudienceButton/VoteAudienceButton.js +1 -1
- package/lib/esm/constants/PubSub.d.ts +28 -0
- package/lib/esm/constants/PubSub.js +19 -0
- package/lib/esm/index.d.ts +5 -3
- package/lib/esm/index.js +4 -2
- package/lib/esm/types/index.d.ts +2 -1
- package/lib/umd/311.js +2 -0
- package/lib/umd/react-ui.js +1 -1
- package/package.json +10 -10
- package/lib/umd/871.js +0 -2
- /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';
|
|
@@ -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 ||
|
|
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) =>
|
|
189
|
-
|
|
190
|
-
|
|
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) =>
|
|
197
|
-
|
|
198
|
-
|
|
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
|
|
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
|
|
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(() => (
|
|
171
|
+
const handleSubscribeAction = useMemo(() => (user) => {
|
|
173
172
|
const newRequests = [...state.results];
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
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) ||
|
|
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,
|
|
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,
|
|
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
|
|
10
|
+
* Handles callback on delete success
|
|
11
11
|
*/
|
|
12
|
-
|
|
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
|
|
16
|
+
user: SCUserType;
|
|
25
17
|
/**
|
|
26
18
|
* The group obj
|
|
27
19
|
*/
|
|
28
|
-
group
|
|
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,
|
|
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
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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: "
|
|
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:
|
|
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"
|
|
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
|
-
*
|
|
19
|
+
* The user to be accepted into the group
|
|
20
20
|
* @default null
|
|
21
21
|
*/
|
|
22
|
-
|
|
22
|
+
user?: SCUserType;
|
|
23
23
|
/**
|
|
24
24
|
* onSubscribe callback
|
|
25
25
|
* @param user
|