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

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 (187) 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 +6 -6
  27. package/lib/cjs/components/GroupHeader/GroupHeader.js +53 -12
  28. package/lib/cjs/components/GroupInfoWidget/GroupInfoWidget.js +63 -9
  29. package/lib/cjs/components/GroupInviteButton/GroupInviteButton.js +31 -9
  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.d.ts +5 -0
  39. package/lib/cjs/components/GroupMembersButton/GroupMembersButton.js +8 -3
  40. package/lib/cjs/components/GroupMembersWidget/GroupMembersWidget.js +25 -4
  41. package/lib/cjs/components/GroupRequestsWidget/GroupRequestsWidget.d.ts +12 -7
  42. package/lib/cjs/components/GroupRequestsWidget/GroupRequestsWidget.js +19 -9
  43. package/lib/cjs/components/GroupSettingsIconButton/GroupSettingsIconButton.d.ts +48 -0
  44. package/lib/cjs/components/GroupSettingsIconButton/GroupSettingsIconButton.js +151 -0
  45. package/lib/cjs/components/GroupSettingsIconButton/index.d.ts +3 -0
  46. package/lib/cjs/components/GroupSettingsIconButton/index.js +5 -0
  47. package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.d.ts +8 -3
  48. package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.js +30 -11
  49. package/lib/cjs/components/Groups/Groups.d.ts +15 -8
  50. package/lib/cjs/components/Groups/Groups.js +86 -32
  51. package/lib/cjs/components/Groups/Skeleton.d.ts +4 -0
  52. package/lib/cjs/components/Groups/Skeleton.js +2 -2
  53. package/lib/cjs/components/InlineComposerWidget/InlineComposerWidget.js +7 -0
  54. package/lib/cjs/components/NavigationSettingsIconButton/NavigationSettingsIconButton.js +4 -4
  55. package/lib/cjs/components/NavigationToolbar/NavigationToolbar.js +9 -2
  56. package/lib/cjs/components/NavigationToolbarMobile/NavigationToolbarMobile.d.ts +1 -0
  57. package/lib/cjs/components/NavigationToolbarMobile/NavigationToolbarMobile.js +9 -1
  58. package/lib/cjs/components/Notification/Group/Group.d.ts +15 -0
  59. package/lib/cjs/components/Notification/Group/Group.js +78 -0
  60. package/lib/cjs/components/Notification/Group/index.d.ts +3 -0
  61. package/lib/cjs/components/Notification/Group/index.js +5 -0
  62. package/lib/cjs/components/Notification/Notification.js +31 -1
  63. package/lib/cjs/components/Notification/PrivateMessage/PrivateMessage.js +16 -5
  64. package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.d.ts +7 -1
  65. package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.js +16 -8
  66. package/lib/cjs/components/PrivateMessageSettingsIconButton/PrivateMessageSettingsIconButton.js +1 -1
  67. package/lib/cjs/components/PrivateMessageSnippetItem/PrivateMessageSnippetItem.js +11 -6
  68. package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.d.ts +9 -4
  69. package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.js +24 -6
  70. package/lib/cjs/components/PrivateMessageThread/PrivateMessageThread.d.ts +6 -1
  71. package/lib/cjs/components/PrivateMessageThread/PrivateMessageThread.js +46 -20
  72. package/lib/cjs/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +6 -0
  73. package/lib/cjs/components/SearchAutocomplete/SearchAutocomplete.js +22 -5
  74. package/lib/cjs/components/SnippetNotifications/SnippetNotifications.js +7 -0
  75. package/lib/cjs/components/ToastNotifications/ToastNotifications.js +7 -0
  76. package/lib/cjs/components/User/User.d.ts +6 -1
  77. package/lib/cjs/components/User/User.js +5 -4
  78. package/lib/cjs/components/UserSubscribedGroupsWidget/Skeleton.d.ts +21 -0
  79. package/lib/cjs/components/UserSubscribedGroupsWidget/Skeleton.js +46 -0
  80. package/lib/cjs/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.d.ts +68 -0
  81. package/lib/cjs/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.js +183 -0
  82. package/lib/cjs/components/UserSubscribedGroupsWidget/constants.d.ts +1 -0
  83. package/lib/cjs/components/UserSubscribedGroupsWidget/constants.js +4 -0
  84. package/lib/cjs/components/UserSubscribedGroupsWidget/index.d.ts +4 -0
  85. package/lib/cjs/components/UserSubscribedGroupsWidget/index.js +8 -0
  86. package/lib/cjs/components/VoteAudienceButton/VoteAudienceButton.js +1 -1
  87. package/lib/cjs/constants/PubSub.d.ts +28 -0
  88. package/lib/cjs/constants/PubSub.js +22 -0
  89. package/lib/cjs/index.d.ts +6 -3
  90. package/lib/cjs/index.js +13 -4
  91. package/lib/cjs/types/index.d.ts +2 -1
  92. package/lib/esm/components/AccountRecover/AccountRecover.js +6 -1
  93. package/lib/esm/components/BottomNavigation/BottomNavigation.js +5 -4
  94. package/lib/esm/components/CategoryHeader/Skeleton.js +3 -2
  95. package/lib/esm/components/ChangeGroupCover/ChangeGroupCover.js +6 -6
  96. package/lib/esm/components/ChangeGroupPicture/ChangeGroupPicture.js +19 -16
  97. package/lib/esm/components/Composer/Attributes/Attributes.js +3 -3
  98. package/lib/esm/components/Composer/Composer.js +3 -3
  99. package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.d.ts +1 -1
  100. package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.js +9 -19
  101. package/lib/esm/components/Editor/Editor.js +2 -0
  102. package/lib/esm/components/Editor/nodes/ImageNode.js +6 -0
  103. package/lib/esm/components/Editor/plugins/ImagePlugin.js +4 -0
  104. package/lib/esm/components/Editor/plugins/ToolbarPlugin.js +19 -5
  105. package/lib/esm/components/FeedObject/Actions/Share/Share.js +19 -17
  106. package/lib/esm/components/FeedObject/Contributors/Contributors.js +1 -1
  107. package/lib/esm/components/FeedObject/FeedObject.d.ts +1 -0
  108. package/lib/esm/components/FeedObject/FeedObject.js +28 -9
  109. package/lib/esm/components/FeedObject/Poll/Poll.js +20 -20
  110. package/lib/esm/components/FeedUpdatesWidget/FeedUpdatesWidget.js +1 -1
  111. package/lib/esm/components/Footer/Footer.js +2 -2
  112. package/lib/esm/components/Group/Group.d.ts +9 -1
  113. package/lib/esm/components/Group/Group.js +22 -10
  114. package/lib/esm/components/GroupAutocomplete/GroupAutocomplete.d.ts +0 -1
  115. package/lib/esm/components/GroupAutocomplete/GroupAutocomplete.js +1 -2
  116. package/lib/esm/components/GroupForm/GroupForm.js +64 -13
  117. package/lib/esm/components/GroupHeader/GroupHeader.d.ts +6 -6
  118. package/lib/esm/components/GroupHeader/GroupHeader.js +55 -14
  119. package/lib/esm/components/GroupInfoWidget/GroupInfoWidget.js +63 -9
  120. package/lib/esm/components/GroupInviteButton/GroupInviteButton.js +31 -9
  121. package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.d.ts +73 -0
  122. package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.js +217 -0
  123. package/lib/esm/components/GroupInvitedWidget/Skeleton.d.ts +22 -0
  124. package/lib/esm/components/GroupInvitedWidget/Skeleton.js +34 -0
  125. package/lib/esm/components/GroupInvitedWidget/constants.d.ts +1 -0
  126. package/lib/esm/components/GroupInvitedWidget/constants.js +1 -0
  127. package/lib/esm/components/GroupInvitedWidget/index.d.ts +4 -0
  128. package/lib/esm/components/GroupInvitedWidget/index.js +4 -0
  129. package/lib/esm/components/GroupMembersButton/GroupMembersButton.d.ts +5 -0
  130. package/lib/esm/components/GroupMembersButton/GroupMembersButton.js +9 -4
  131. package/lib/esm/components/GroupMembersWidget/GroupMembersWidget.js +26 -5
  132. package/lib/esm/components/GroupRequestsWidget/GroupRequestsWidget.d.ts +12 -7
  133. package/lib/esm/components/GroupRequestsWidget/GroupRequestsWidget.js +19 -9
  134. package/lib/esm/components/GroupSettingsIconButton/GroupSettingsIconButton.d.ts +48 -0
  135. package/lib/esm/components/GroupSettingsIconButton/GroupSettingsIconButton.js +148 -0
  136. package/lib/esm/components/GroupSettingsIconButton/index.d.ts +3 -0
  137. package/lib/esm/components/GroupSettingsIconButton/index.js +2 -0
  138. package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.d.ts +8 -3
  139. package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.js +30 -11
  140. package/lib/esm/components/Groups/Groups.d.ts +15 -8
  141. package/lib/esm/components/Groups/Groups.js +91 -37
  142. package/lib/esm/components/Groups/Skeleton.d.ts +4 -0
  143. package/lib/esm/components/Groups/Skeleton.js +2 -2
  144. package/lib/esm/components/InlineComposerWidget/InlineComposerWidget.js +9 -2
  145. package/lib/esm/components/NavigationSettingsIconButton/NavigationSettingsIconButton.js +4 -4
  146. package/lib/esm/components/NavigationToolbar/NavigationToolbar.js +10 -3
  147. package/lib/esm/components/NavigationToolbarMobile/NavigationToolbarMobile.d.ts +1 -0
  148. package/lib/esm/components/NavigationToolbarMobile/NavigationToolbarMobile.js +11 -3
  149. package/lib/esm/components/Notification/Group/Group.d.ts +15 -0
  150. package/lib/esm/components/Notification/Group/Group.js +75 -0
  151. package/lib/esm/components/Notification/Group/index.d.ts +3 -0
  152. package/lib/esm/components/Notification/Group/index.js +2 -0
  153. package/lib/esm/components/Notification/Notification.js +31 -1
  154. package/lib/esm/components/Notification/PrivateMessage/PrivateMessage.js +16 -5
  155. package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.d.ts +7 -1
  156. package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.js +17 -9
  157. package/lib/esm/components/PrivateMessageSettingsIconButton/PrivateMessageSettingsIconButton.js +1 -1
  158. package/lib/esm/components/PrivateMessageSnippetItem/PrivateMessageSnippetItem.js +11 -6
  159. package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.d.ts +9 -4
  160. package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.js +26 -8
  161. package/lib/esm/components/PrivateMessageThread/PrivateMessageThread.d.ts +6 -1
  162. package/lib/esm/components/PrivateMessageThread/PrivateMessageThread.js +48 -22
  163. package/lib/esm/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +7 -1
  164. package/lib/esm/components/SearchAutocomplete/SearchAutocomplete.js +22 -5
  165. package/lib/esm/components/SnippetNotifications/SnippetNotifications.js +7 -0
  166. package/lib/esm/components/ToastNotifications/ToastNotifications.js +7 -0
  167. package/lib/esm/components/User/User.d.ts +6 -1
  168. package/lib/esm/components/User/User.js +5 -4
  169. package/lib/esm/components/UserSubscribedGroupsWidget/Skeleton.d.ts +21 -0
  170. package/lib/esm/components/UserSubscribedGroupsWidget/Skeleton.js +42 -0
  171. package/lib/esm/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.d.ts +68 -0
  172. package/lib/esm/components/UserSubscribedGroupsWidget/UserSubscribedGroupsWidget.js +180 -0
  173. package/lib/esm/components/UserSubscribedGroupsWidget/constants.d.ts +1 -0
  174. package/lib/esm/components/UserSubscribedGroupsWidget/constants.js +1 -0
  175. package/lib/esm/components/UserSubscribedGroupsWidget/index.d.ts +4 -0
  176. package/lib/esm/components/UserSubscribedGroupsWidget/index.js +4 -0
  177. package/lib/esm/components/VoteAudienceButton/VoteAudienceButton.js +1 -1
  178. package/lib/esm/constants/PubSub.d.ts +28 -0
  179. package/lib/esm/constants/PubSub.js +19 -0
  180. package/lib/esm/index.d.ts +6 -3
  181. package/lib/esm/index.js +6 -3
  182. package/lib/esm/types/index.d.ts +2 -1
  183. package/lib/umd/311.js +2 -0
  184. package/lib/umd/react-ui.js +1 -1
  185. package/package.json +9 -9
  186. package/lib/umd/871.js +0 -2
  187. /package/lib/umd/{871.js.LICENSE.txt → 311.js.LICENSE.txt} +0 -0
@@ -5,7 +5,7 @@ import { styled } from '@mui/material/styles';
5
5
  import { Box, Button, Typography } from '@mui/material';
6
6
  import classNames from 'classnames';
7
7
  import { CustomMenuService } from '@selfcommunity/api-services';
8
- import { Logger } from '@selfcommunity/utils';
8
+ import { Logger, sortByAttr } from '@selfcommunity/utils';
9
9
  import { Link, SCPreferences, useSCPreferences } from '@selfcommunity/react-core';
10
10
  import { SCOPE_SC_UI } from '../../constants/Errors';
11
11
  import FooterSkeleton from './Skeleton';
@@ -94,7 +94,7 @@ export default function Footer(inProps) {
94
94
  }
95
95
  return (React.createElement(Root, Object.assign({}, rest, { className: classNames(classes.root, className) }),
96
96
  startActions,
97
- React.createElement(Box, { className: classes.itemList }, _menu.items.map((item, index) => (React.createElement(Button, { component: Link, key: item.id, className: classes.item, to: item.url, variant: "text" }, item.label)))),
97
+ React.createElement(Box, { className: classes.itemList }, sortByAttr(_menu.items, 'order').map((item, index) => (React.createElement(Button, { component: Link, key: item.id, className: classes.item, to: item.url, variant: "text" }, item.label)))),
98
98
  endActions,
99
99
  React.createElement(Typography, { textAlign: "center", className: classes.copyright, variant: "body2", dangerouslySetInnerHTML: { __html: copyright } })));
100
100
  }
@@ -27,6 +27,11 @@ export interface GroupProps extends WidgetProps {
27
27
  * @default false
28
28
  */
29
29
  hideActions?: boolean;
30
+ /**
31
+ * Prop to redirect the user to the group page
32
+ * @default false
33
+ */
34
+ actionRedirect?: boolean;
30
35
  /**
31
36
  * Props to spread to the button
32
37
  * @default {}
@@ -42,7 +47,7 @@ export interface GroupProps extends WidgetProps {
42
47
  *
43
48
  *
44
49
  * This component renders a group item.
45
- * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/User)
50
+ * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/Group)
46
51
 
47
52
  #### Import
48
53
 
@@ -61,6 +66,9 @@ export interface GroupProps extends WidgetProps {
61
66
  |---|---|---|
62
67
  |root|.SCGroup-root|Styles applied to the root element.|
63
68
  |avatar|.SCGroup-avatar|Styles applied to the avatar element.|
69
+ |actions|.SCGroup-actions|Styles applied to the actions section.|
70
+ |icon|.SCGroup-icon|Styles applied to the group privacy icon element.|
71
+
64
72
 
65
73
  *
66
74
  * @param inProps
@@ -1,9 +1,10 @@
1
1
  import { __rest } from "tslib";
2
- import React, { useState } from 'react';
2
+ import React, { useMemo, useState } from 'react';
3
3
  import { styled } from '@mui/material/styles';
4
- import { Avatar, Icon, Stack } from '@mui/material';
5
- import { Link, SCRoutes, useSCFetchGroup, useSCRouting } from '@selfcommunity/react-core';
6
- import { defineMessages, useIntl } from 'react-intl';
4
+ import { Avatar, Button, Icon, Stack } from '@mui/material';
5
+ import { SCGroupPrivacyType, SCGroupSubscriptionStatusType } from '@selfcommunity/types';
6
+ import { Link, SCRoutes, useSCFetchGroup, useSCRouting, useSCUser } from '@selfcommunity/react-core';
7
+ import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
7
8
  import classNames from 'classnames';
8
9
  import { useThemeProps } from '@mui/system';
9
10
  import BaseItemButton from '../../shared/BaseItemButton';
@@ -20,7 +21,8 @@ const messages = defineMessages({
20
21
  const classes = {
21
22
  root: `${PREFIX}-root`,
22
23
  avatar: `${PREFIX}-avatar`,
23
- actions: `${PREFIX}-actions`
24
+ actions: `${PREFIX}-actions`,
25
+ icon: `${PREFIX}-icon`
24
26
  };
25
27
  const Root = styled(BaseItemButton, {
26
28
  name: PREFIX,
@@ -32,7 +34,7 @@ const Root = styled(BaseItemButton, {
32
34
  *
33
35
  *
34
36
  * This component renders a group item.
35
- * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/User)
37
+ * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/Group)
36
38
 
37
39
  #### Import
38
40
 
@@ -51,21 +53,28 @@ const Root = styled(BaseItemButton, {
51
53
  |---|---|---|
52
54
  |root|.SCGroup-root|Styles applied to the root element.|
53
55
  |avatar|.SCGroup-avatar|Styles applied to the avatar element.|
56
+ |actions|.SCGroup-actions|Styles applied to the actions section.|
57
+ |icon|.SCGroup-icon|Styles applied to the group privacy icon element.|
58
+
54
59
 
55
60
  *
56
61
  * @param inProps
57
62
  */
58
63
  export default function Group(inProps) {
64
+ var _a;
59
65
  // PROPS
60
66
  const props = useThemeProps({
61
67
  props: inProps,
62
68
  name: PREFIX
63
69
  });
64
- const { groupId = null, group = null, className = null, elevation, hideActions = false, groupSubscribeButtonProps = {}, visible = true } = props, rest = __rest(props, ["groupId", "group", "className", "elevation", "hideActions", "groupSubscribeButtonProps", "visible"]);
70
+ const { groupId = null, group = null, className = null, elevation, hideActions = false, actionRedirect = false, groupSubscribeButtonProps = {} } = props, rest = __rest(props, ["groupId", "group", "className", "elevation", "hideActions", "actionRedirect", "groupSubscribeButtonProps"]);
65
71
  // STATE
66
72
  const { scGroup } = useSCFetchGroup({ id: groupId, group });
67
73
  // CONTEXT
68
74
  const scRoutingContext = useSCRouting();
75
+ const scUserContext = useSCUser();
76
+ // CONST
77
+ 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]);
69
78
  const [openAlert, setOpenAlert] = useState(false);
70
79
  // INTL
71
80
  const intl = useIntl();
@@ -75,8 +84,8 @@ export default function Group(inProps) {
75
84
  */
76
85
  function renderAuthenticatedActions() {
77
86
  return (React.createElement(Stack, { className: classes.actions, direction: "row", alignItems: "center", justifyContent: "center", spacing: 2 },
78
- React.createElement(Icon, null, !visible ? 'private' : 'public'),
79
- React.createElement(GroupSubscribeButton, Object.assign({ group: group, groupId: groupId }, groupSubscribeButtonProps))));
87
+ isGroupAdmin && React.createElement(Icon, null, "face"),
88
+ actionRedirect ? (React.createElement(Button, { size: "small", variant: "outlined", component: Link, to: scRoutingContext.url(SCRoutes.GROUP_ROUTE_NAME, scGroup) }, scGroup.subscription_status === SCGroupSubscriptionStatusType.SUBSCRIBED ? (React.createElement(FormattedMessage, { defaultMessage: "ui.group.status.enter", id: "ui.group.status.enter" })) : (React.createElement(FormattedMessage, { defaultMessage: "ui.group.status.discover", id: "ui.group.status.discover" })))) : (React.createElement(GroupSubscribeButton, Object.assign({ group: group, groupId: groupId }, groupSubscribeButtonProps)))));
80
89
  }
81
90
  /**
82
91
  * Renders group object
@@ -88,6 +97,9 @@ export default function Group(inProps) {
88
97
  * Renders root object
89
98
  */
90
99
  return (React.createElement(React.Fragment, null,
91
- React.createElement(Root, Object.assign({ elevation: elevation }, rest, { className: classNames(classes.root, className), ButtonBaseProps: { component: Link, to: scRoutingContext.url(SCRoutes.GROUP_ROUTE_NAME, scGroup) }, image: React.createElement(Avatar, { alt: scGroup.name, src: scGroup.image_medium, className: classes.avatar }), primary: scGroup.name, secondary: `${intl.formatMessage(messages.groupMembers, { total: scGroup.subscribers_counter })}`, actions: hideActions ? null : renderAuthenticatedActions() })),
100
+ React.createElement(Root, Object.assign({ elevation: elevation }, rest, { className: classNames(classes.root, className), ButtonBaseProps: { component: Link, to: scRoutingContext.url(SCRoutes.GROUP_ROUTE_NAME, scGroup) }, image: React.createElement(Avatar, { alt: scGroup.name, src: scGroup.image_medium, className: classes.avatar }), primary: React.createElement(React.Fragment, null,
101
+ scGroup.name,
102
+ " ",
103
+ React.createElement(Icon, { className: classes.icon }, (group === null || group === void 0 ? void 0 : group.privacy) === SCGroupPrivacyType.PRIVATE ? 'private' : 'public')), secondary: `${intl.formatMessage(messages.groupMembers, { total: scGroup.subscribers_counter })}`, actions: hideActions ? null : renderAuthenticatedActions() })),
92
104
  openAlert && React.createElement(UserDeletedSnackBar, { open: openAlert, handleClose: () => setOpenAlert(false) })));
93
105
  }
@@ -28,7 +28,6 @@ export interface GroupAutocompleteProps extends Pick<AutocompleteProps<SCGroupTy
28
28
  *
29
29
  *
30
30
  * This component renders a bar that allows users to search (with autocomplete) for all the groups available in the application.
31
- * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/GroupAutocomplete)
32
31
  *
33
32
  * #### Import
34
33
  * ```jsx
@@ -24,7 +24,6 @@ const Root = styled(Autocomplete, {
24
24
  *
25
25
  *
26
26
  * This component renders a bar that allows users to search (with autocomplete) for all the groups available in the application.
27
- * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/GroupAutocomplete)
28
27
  *
29
28
  * #### Import
30
29
  * ```jsx
@@ -78,7 +77,7 @@ const GroupAutocomplete = (inProps) => {
78
77
  setValue(value);
79
78
  };
80
79
  // Render
81
- return (React.createElement(Root, Object.assign({ freeSolo: true, className: classes.root, open: open, onOpen: handleOpen, onClose: handleClose, options: groups || [], getOptionLabel: (option) => option.name || '', value: value, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: React.createElement(FormattedMessage, { id: "ui.groupAutocomplete.empty", defaultMessage: "ui.groupAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, value) => value.id === option.id,
80
+ return (React.createElement(Root, Object.assign({ className: classes.root, open: open, onOpen: handleOpen, onClose: handleClose, options: groups || [], getOptionLabel: (option) => option.name || '', value: value, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: React.createElement(FormattedMessage, { id: "ui.groupAutocomplete.empty", defaultMessage: "ui.groupAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, value) => value.id === option.id,
82
81
  // renderTags={(value, getTagProps) => {
83
82
  // return value.map((option: any, index) => (
84
83
  // <Chip key={option.id} id={option.id} label={option.name} color={option.color} {...getTagProps({index})} />
@@ -13,10 +13,12 @@ import ChangeGroupPicture from '../ChangeGroupPicture';
13
13
  import ChangeGroupCover from '../ChangeGroupCover';
14
14
  import { GROUP_DESCRIPTION_MAX_LENGTH, GROUP_TITLE_MAX_LENGTH } from '../../constants/Group';
15
15
  import GroupInviteButton from '../GroupInviteButton';
16
+ import PubSub from 'pubsub-js';
16
17
  import { SCGroupPrivacyType } from '@selfcommunity/types';
17
18
  import { SCOPE_SC_UI } from '../../constants/Errors';
18
19
  import { formatHttpErrorCode, GroupService } from '@selfcommunity/api-services';
19
20
  import { Logger } from '@selfcommunity/utils';
21
+ import { SCEventType, SCTopicType } from '../../constants/PubSub';
20
22
  const messages = defineMessages({
21
23
  name: {
22
24
  id: 'ui.groupForm.name.placeholder',
@@ -88,6 +90,7 @@ const Root = styled(BaseDialog, {
88
90
  * @param inProps
89
91
  */
90
92
  export default function GroupForm(inProps) {
93
+ var _a;
91
94
  //PROPS
92
95
  const props = useThemeProps({
93
96
  props: inProps,
@@ -140,6 +143,22 @@ export default function GroupForm(inProps) {
140
143
  setError(error);
141
144
  }
142
145
  }
146
+ /**
147
+ * Notify when a group info changed
148
+ * @param data
149
+ */
150
+ function notifyChanges(data) {
151
+ if (data) {
152
+ if (group) {
153
+ // Edit group
154
+ PubSub.publish(`${SCTopicType.GROUP}.${SCEventType.EDIT}`, data);
155
+ }
156
+ else {
157
+ // Create group
158
+ PubSub.publish(`${SCTopicType.GROUP}.${SCEventType.CREATE}`, data);
159
+ }
160
+ }
161
+ }
143
162
  const handleSubmit = () => {
144
163
  setField((prev) => (Object.assign(Object.assign({}, prev), { ['isSubmitting']: true })));
145
164
  const formData = new FormData();
@@ -153,8 +172,10 @@ export default function GroupForm(inProps) {
153
172
  if (field.emotionalImageOriginalFile) {
154
173
  formData.append('emotional_image_original', field.emotionalImageOriginalFile);
155
174
  }
156
- for (const key in field.invitedUsers) {
157
- formData.append(key, field.invitedUsers[key]);
175
+ if (!group) {
176
+ for (const key in field.invitedUsers) {
177
+ formData.append(key, field.invitedUsers[key]);
178
+ }
158
179
  }
159
180
  let groupService;
160
181
  if (group) {
@@ -166,6 +187,7 @@ export default function GroupForm(inProps) {
166
187
  groupService
167
188
  .then((data) => {
168
189
  onSuccess && onSuccess(data);
190
+ notifyChanges(data);
169
191
  onClose && onClose();
170
192
  setField((prev) => (Object.assign(Object.assign({}, prev), { ['isSubmitting']: false })));
171
193
  })
@@ -204,33 +226,62 @@ export default function GroupForm(inProps) {
204
226
  endAdornment: React.createElement(Typography, { variant: "body2" }, GROUP_TITLE_MAX_LENGTH - field.name.length)
205
227
  } }),
206
228
  React.createElement(TextField, { multiline: true, className: classes.description, placeholder: `${intl.formatMessage(messages.description)}`, margin: "normal", value: field.description, name: "description", onChange: handleChange, InputProps: {
207
- endAdornment: React.createElement(Typography, { variant: "body2" }, GROUP_DESCRIPTION_MAX_LENGTH - field.description.length)
229
+ endAdornment: (React.createElement(Typography, { variant: "body2" }, ((_a = field.description) === null || _a === void 0 ? void 0 : _a.length) ? GROUP_DESCRIPTION_MAX_LENGTH - field.description.length : GROUP_DESCRIPTION_MAX_LENGTH))
208
230
  } }),
209
231
  React.createElement(Box, { className: classes.privacySection },
210
232
  React.createElement(Typography, { variant: "h4" },
211
- React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.title", defaultMessage: "ui.groupForm.privacy.title", values: { b: (chunks) => React.createElement("strong", null, chunks) } })),
233
+ React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.title", defaultMessage: "ui.groupForm.privacy.title", values: {
234
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
235
+ // @ts-ignore
236
+ b: (chunks) => React.createElement("strong", null, chunks)
237
+ } })),
212
238
  React.createElement(Stack, { direction: "row", spacing: 1, alignItems: "center" },
213
239
  React.createElement(Typography, { className: classNames(classes.switchLabel, { [classes.active]: !field.isPublic }) },
214
240
  React.createElement(Icon, null, "private"),
215
241
  React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.private", defaultMessage: "ui.groupForm.privacy.private" })),
216
- React.createElement(Switch, { className: classes.switch, checked: field.isPublic, onClick: () => setField((prev) => (Object.assign(Object.assign({}, prev), { ['isPublic']: !field.isPublic }))) }),
242
+ React.createElement(Switch, { className: classes.switch, checked: field.isPublic, onChange: () => setField((prev) => (Object.assign(Object.assign({}, prev), { ['isPublic']: !field.isPublic }))), disabled: group && group.privacy === SCGroupPrivacyType.PRIVATE }),
217
243
  React.createElement(Typography, { className: classNames(classes.switchLabel, { [classes.active]: field.isPublic }) },
218
244
  React.createElement(Icon, null, "public"),
219
245
  React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.public", defaultMessage: "ui.groupForm.privacy.public" }))),
220
- React.createElement(Typography, { variant: "body2", className: classes.privacySectionInfo }, field.isPublic ? (React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.public.info", defaultMessage: "ui.groupForm.privacy.public.info", values: { b: (chunks) => React.createElement("strong", null, chunks) } })) : (React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.private.info", defaultMessage: "ui.groupForm.private.public.info", values: { b: (chunks) => React.createElement("strong", null, chunks) } })))),
221
- React.createElement(Box, { className: classes.visibilitySection }, !field.isPublic && (React.createElement(React.Fragment, null,
246
+ React.createElement(Typography, { variant: "body2", className: classes.privacySectionInfo }, field.isPublic ? (React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.public.info", defaultMessage: "ui.groupForm.privacy.public.info", values: {
247
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
248
+ // @ts-ignore
249
+ b: (chunks) => React.createElement("strong", null, chunks)
250
+ } })) : (React.createElement(React.Fragment, null, group && group.privacy === SCGroupPrivacyType.PRIVATE ? (React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.private.info.edit", defaultMessage: "ui.groupForm.private.public.info.edit", values: {
251
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
252
+ // @ts-ignore
253
+ b: (chunks) => React.createElement("strong", null, chunks)
254
+ } })) : (React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.private.info", defaultMessage: "ui.groupForm.private.public.info", values: {
255
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
256
+ // @ts-ignore
257
+ b: (chunks) => React.createElement("strong", null, chunks)
258
+ } })))))),
259
+ React.createElement(Box, { className: classes.visibilitySection }, ((!field.isPublic && !group) || (group && !field.isPublic)) && (React.createElement(React.Fragment, null,
222
260
  React.createElement(Typography, { variant: "h4" },
223
- React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.title", defaultMessage: "ui.groupForm.visibility.title", values: { b: (chunks) => React.createElement("strong", null, chunks) } })),
261
+ React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.title", defaultMessage: "ui.groupForm.visibility.title", values: {
262
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
263
+ // @ts-ignore
264
+ b: (chunks) => React.createElement("strong", null, chunks)
265
+ } })),
224
266
  React.createElement(Stack, { direction: "row", spacing: 1, alignItems: "center" },
225
267
  React.createElement(Typography, { className: classNames(classes.switchLabel, { [classes.active]: !field.isVisible }) },
226
268
  React.createElement(Icon, null, "visibility_off"),
227
269
  React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.hidden", defaultMessage: "ui.groupForm.visibility.hidden" })),
228
- React.createElement(Switch, { className: classes.switch, checked: field.isVisible, onClick: () => setField((prev) => (Object.assign(Object.assign({}, prev), { ['isVisible']: !field.isVisible }))) }),
270
+ React.createElement(Switch, { className: classes.switch, checked: field.isVisible, onChange: () => setField((prev) => (Object.assign(Object.assign({}, prev), { ['isVisible']: !field.isVisible }))) }),
229
271
  React.createElement(Typography, { className: classNames(classes.switchLabel, { [classes.active]: field.isVisible }) },
230
272
  React.createElement(Icon, null, "visibility"),
231
273
  React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.visible", defaultMessage: "ui.groupForm.visibility.visible" }))),
232
- React.createElement(Typography, { variant: "body2", className: classes.visibilitySectionInfo }, !field.isVisible ? (React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.hidden.info", defaultMessage: "ui.groupForm.visibility.hidden.info", values: { b: (chunks) => React.createElement("strong", null, chunks) } })) : (React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.visible.info", defaultMessage: "ui.groupForm.visibility.visible.info", values: { b: (chunks) => React.createElement("strong", null, chunks) } }))))))),
233
- React.createElement(Divider, null),
234
- React.createElement(Box, { className: classes.inviteSection },
235
- React.createElement(GroupInviteButton, { handleInvitations: handleInviteSection })))));
274
+ React.createElement(Typography, { variant: "body2", className: classes.visibilitySectionInfo }, !field.isVisible ? (React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.hidden.info", defaultMessage: "ui.groupForm.visibility.hidden.info", values: {
275
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
276
+ // @ts-ignore
277
+ b: (chunks) => React.createElement("strong", null, chunks)
278
+ } })) : (React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.visible.info", defaultMessage: "ui.groupForm.visibility.visible.info", values: {
279
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
280
+ // @ts-ignore
281
+ b: (chunks) => React.createElement("strong", null, chunks)
282
+ } }))))))),
283
+ !group && (React.createElement(React.Fragment, null,
284
+ React.createElement(Divider, null),
285
+ React.createElement(Box, { className: classes.inviteSection },
286
+ React.createElement(GroupInviteButton, { handleInvitations: handleInviteSection })))))));
236
287
  }
@@ -1,8 +1,8 @@
1
- import React from 'react';
2
1
  import { SCGroupType } from '@selfcommunity/types';
3
2
  import { ChangeGroupCoverProps } from '../ChangeGroupCover';
4
3
  import { ChangeGroupPictureProps } from '../ChangeGroupPicture';
5
4
  import { GroupMembersButtonProps } from '../GroupMembersButton';
5
+ import { GroupSubscribeButtonProps } from '../GroupSubscribeButton';
6
6
  export interface GroupHeaderProps {
7
7
  /**
8
8
  * Id of group object
@@ -35,14 +35,15 @@ export interface GroupHeaderProps {
35
35
  */
36
36
  ChangeCoverProps?: ChangeGroupCoverProps;
37
37
  /**
38
- * Props to spread to the group memebers button
38
+ * Props to spread group button followed
39
39
  * @default {}
40
40
  */
41
- GroupMembersButtonProps?: GroupMembersButtonProps;
41
+ GroupSubscribeButtonProps?: GroupSubscribeButtonProps;
42
42
  /**
43
- *
43
+ * Props to spread to the group memebers button
44
+ * @default {}
44
45
  */
45
- actions?: React.ReactNode;
46
+ GroupMembersButtonProps?: GroupMembersButtonProps;
46
47
  /**
47
48
  * Any other properties
48
49
  */
@@ -53,7 +54,6 @@ export interface GroupHeaderProps {
53
54
  *
54
55
  *
55
56
  * This component renders the groups top section.
56
- * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/UserProfileHeader)
57
57
 
58
58
  #### Import
59
59
 
@@ -1,8 +1,8 @@
1
1
  import { __rest } from "tslib";
2
- import React, { useMemo } from 'react';
2
+ import React, { useCallback, useEffect, useMemo, useRef } from 'react';
3
3
  import { styled } from '@mui/material/styles';
4
4
  import { Avatar, Box, Icon, Paper, Typography } from '@mui/material';
5
- import { SCGroupPrivacyType } from '@selfcommunity/types';
5
+ import { SCGroupPrivacyType, SCGroupSubscriptionStatusType } from '@selfcommunity/types';
6
6
  import { SCPreferences, useSCFetchGroup, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
7
7
  import GroupHeaderSkeleton from './Skeleton';
8
8
  import classNames from 'classnames';
@@ -14,6 +14,10 @@ import Bullet from '../../shared/Bullet';
14
14
  import ChangeGroupPicture from '../ChangeGroupPicture';
15
15
  import GroupMembersButton from '../GroupMembersButton';
16
16
  import EditGroupButton from '../EditGroupButton';
17
+ import GroupSubscribeButton from '../GroupSubscribeButton';
18
+ import GroupInviteButton from '../GroupInviteButton';
19
+ import { SCEventType, SCTopicType } from '../../constants/PubSub';
20
+ import PubSub from 'pubsub-js';
17
21
  const classes = {
18
22
  root: `${PREFIX}-root`,
19
23
  cover: `${PREFIX}-cover`,
@@ -36,7 +40,6 @@ const Root = styled(Box, {
36
40
  *
37
41
  *
38
42
  * This component renders the groups top section.
39
- * Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/UserProfileHeader)
40
43
 
41
44
  #### Import
42
45
 
@@ -70,22 +73,24 @@ export default function GroupHeader(inProps) {
70
73
  props: inProps,
71
74
  name: PREFIX
72
75
  });
73
- const { id = null, className = null, group, groupId = null, ChangePictureProps = {}, ChangeCoverProps = {}, GroupMembersButtonProps = {}, actions } = props, rest = __rest(props, ["id", "className", "group", "groupId", "ChangePictureProps", "ChangeCoverProps", "GroupMembersButtonProps", "actions"]);
76
+ const { id = null, className = null, group, groupId = null, ChangePictureProps = {}, ChangeCoverProps = {}, GroupSubscribeButtonProps = {}, GroupMembersButtonProps = {} } = props, rest = __rest(props, ["id", "className", "group", "groupId", "ChangePictureProps", "ChangeCoverProps", "GroupSubscribeButtonProps", "GroupMembersButtonProps"]);
74
77
  // PREFERENCES
75
78
  const scPreferences = useSCPreferences();
76
79
  // CONTEXT
77
80
  const scUserContext = useSCUser();
78
81
  // HOOKS
79
82
  const { scGroup, setSCGroup } = useSCFetchGroup({ id: groupId, group });
83
+ // REFS
84
+ const updatesSubscription = useRef(null);
80
85
  // CONST
81
- const canEdit = useMemo(() => { var _a; return scUserContext.user && ((_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id) === scUserContext.user.id; }, [scUserContext.user, (_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id]);
86
+ 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]);
82
87
  /**
83
88
  * Handles Change Avatar
84
89
  * @param avatar
85
90
  */
86
91
  function handleChangeAvatar(avatar) {
87
- if (canEdit) {
88
- setSCGroup(Object.assign({}, scGroup, { image_bigger: avatar }));
92
+ if (isGroupAdmin) {
93
+ setSCGroup(Object.assign({}, scGroup, { image_big: avatar }));
89
94
  }
90
95
  }
91
96
  /**
@@ -93,10 +98,44 @@ export default function GroupHeader(inProps) {
93
98
  * @param cover
94
99
  */
95
100
  function handleChangeCover(cover) {
96
- if (canEdit) {
101
+ if (isGroupAdmin) {
97
102
  setSCGroup(Object.assign({}, scGroup, { emotional_image: cover }));
98
103
  }
99
104
  }
105
+ /**
106
+ * Handles callback subscribe/unsubscribe group
107
+ */
108
+ const handleSubscribe = (group, status) => {
109
+ setSCGroup(Object.assign(Object.assign({}, group), { subscribers_counter: group.subscribers_counter + (status ? 1 : -1) }));
110
+ };
111
+ /**
112
+ * Subscriber for pubsub callback
113
+ */
114
+ const onChangeGroupMembersHandler = useCallback((msg, data) => {
115
+ var _a;
116
+ if (data && ((_a = data === null || data === void 0 ? void 0 : data.group) === null || _a === void 0 ? void 0 : _a.id) === (scGroup === null || scGroup === void 0 ? void 0 : scGroup.id)) {
117
+ let _group = Object.assign({}, scGroup);
118
+ if (msg === `${SCTopicType.GROUP}.${SCEventType.ADD_MEMBER}`) {
119
+ _group.subscribers_counter = _group.subscribers_counter + 1;
120
+ }
121
+ else if (msg === `${SCTopicType.GROUP}.${SCEventType.REMOVE_MEMBER}`) {
122
+ _group.subscribers_counter = Math.max(_group.subscribers_counter - 1, 0);
123
+ }
124
+ console.log(_group);
125
+ setSCGroup(_group);
126
+ }
127
+ }, [scGroup, setSCGroup]);
128
+ /**
129
+ * On mount, subscribe to receive groups updates (only edit)
130
+ */
131
+ useEffect(() => {
132
+ if (scGroup) {
133
+ updatesSubscription.current = PubSub.subscribe(`${SCTopicType.GROUP}.${SCEventType.MEMBERS}`, onChangeGroupMembersHandler);
134
+ }
135
+ return () => {
136
+ updatesSubscription.current && PubSub.unsubscribe(updatesSubscription.current);
137
+ };
138
+ }, [scGroup]);
100
139
  // RENDER
101
140
  if (!scGroup) {
102
141
  return React.createElement(GroupHeaderSkeleton, null);
@@ -108,13 +147,13 @@ export default function GroupHeader(inProps) {
108
147
  React.createElement(Paper, { style: _backgroundCover, classes: { root: classes.cover } },
109
148
  React.createElement(Box, { className: classes.avatar },
110
149
  React.createElement(Avatar, null,
111
- React.createElement("img", { alt: "group", src: scGroup.image_bigger ? scGroup.image_bigger : '' }))),
112
- canEdit && (React.createElement(React.Fragment, null,
150
+ React.createElement("img", { alt: "group", src: scGroup.image_big ? scGroup.image_big : '' }))),
151
+ isGroupAdmin && (React.createElement(React.Fragment, null,
113
152
  React.createElement(ChangeGroupPicture, Object.assign({ groupId: scGroup.id, onChange: handleChangeAvatar, className: classes.changePicture }, ChangePictureProps)),
114
153
  React.createElement("div", { className: classes.changeCover },
115
154
  React.createElement(ChangeGroupCover, Object.assign({ groupId: scGroup.id, onChange: handleChangeCover }, ChangeCoverProps)))))),
116
155
  React.createElement(Box, { className: classes.info },
117
- canEdit && React.createElement(EditGroupButton, { group: scGroup, groupId: scGroup.id, onEditSuccess: (data) => setSCGroup(data) }),
156
+ isGroupAdmin && React.createElement(EditGroupButton, { group: scGroup, groupId: scGroup.id, onEditSuccess: (data) => setSCGroup(data) }),
118
157
  React.createElement(Typography, { variant: "h5", className: classes.name }, scGroup.name),
119
158
  React.createElement(Box, { className: classes.visibility },
120
159
  scGroup.privacy === SCGroupPrivacyType.PUBLIC ? (React.createElement(Typography, { className: classes.visibilityItem },
@@ -128,9 +167,11 @@ export default function GroupHeader(inProps) {
128
167
  React.createElement(FormattedMessage, { id: "ui.groupHeader.visibility.visible", defaultMessage: "ui.groupHeader.visibility.visible" }))) : (React.createElement(Typography, { className: classes.visibilityItem },
129
168
  React.createElement(Icon, null, "visibility_off"),
130
169
  React.createElement(FormattedMessage, { id: "ui.groupHeader.visibility.hidden", defaultMessage: "ui.groupHeader.visibility.hidden" })))),
131
- React.createElement(Box, { className: classes.members },
170
+ React.createElement(React.Fragment, null, ((scGroup && scGroup.privacy === SCGroupPrivacyType.PUBLIC) ||
171
+ scGroup.subscription_status === SCGroupSubscriptionStatusType.SUBSCRIBED ||
172
+ isGroupAdmin) && (React.createElement(Box, { className: classes.members },
132
173
  React.createElement(Typography, { className: classes.membersCounter, component: "div" },
133
174
  React.createElement(FormattedMessage, { id: "ui.groupHeader.members", defaultMessage: "ui.groupHeader.members", values: { total: scGroup.subscribers_counter } })),
134
- React.createElement(GroupMembersButton, Object.assign({ groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, group: scGroup }, GroupMembersButtonProps))),
135
- actions && actions)));
175
+ React.createElement(GroupMembersButton, Object.assign({ key: scGroup.subscribers_counter, groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, group: scGroup, autoHide: !isGroupAdmin }, GroupMembersButtonProps))))),
176
+ isGroupAdmin ? (React.createElement(GroupInviteButton, { group: scGroup, groupId: scGroup.id })) : (React.createElement(GroupSubscribeButton, Object.assign({ group: scGroup, onSubscribe: handleSubscribe }, GroupSubscribeButtonProps))))));
136
177
  }
@@ -1,5 +1,5 @@
1
1
  import { __rest } from "tslib";
2
- import React from 'react';
2
+ import React, { useCallback, useEffect, useRef } from 'react';
3
3
  import { styled } from '@mui/material/styles';
4
4
  import { CardContent, Icon, Typography } from '@mui/material';
5
5
  import classNames from 'classnames';
@@ -8,7 +8,10 @@ import { useThemeProps } from '@mui/system';
8
8
  import { PREFIX } from './constants';
9
9
  import { FormattedMessage, useIntl } from 'react-intl';
10
10
  import { SCGroupPrivacyType } from '@selfcommunity/types';
11
+ import PubSub from 'pubsub-js';
11
12
  import { useSCFetchGroup } from '@selfcommunity/react-core';
13
+ import GroupInfoWidgetSkeleton from './Skeleton';
14
+ import { SCEventType, SCTopicType } from '../../constants/PubSub';
12
15
  const classes = {
13
16
  root: `${PREFIX}-root`,
14
17
  title: `${PREFIX}-title`,
@@ -17,6 +20,7 @@ const classes = {
17
20
  privacyTitle: `${PREFIX}-privacy-title`,
18
21
  visibility: `${PREFIX}-visibility`,
19
22
  visibilityTitle: `${PREFIX}-visibility-title`,
23
+ admin: `${PREFIX}-admin`,
20
24
  date: `${PREFIX}-date`
21
25
  };
22
26
  const Root = styled(Widget, {
@@ -59,9 +63,36 @@ export default function GroupInfoWidget(inProps) {
59
63
  });
60
64
  const { className, group, groupId, onHeightChange, onStateChange } = props, rest = __rest(props, ["className", "group", "groupId", "onHeightChange", "onStateChange"]);
61
65
  // HOOKS
62
- const { scGroup } = useSCFetchGroup({ id: groupId, group });
66
+ const { scGroup, setSCGroup } = useSCFetchGroup({ id: groupId, group });
63
67
  // INTL
64
68
  const intl = useIntl();
69
+ // REFS
70
+ const updatesSubscription = useRef(null);
71
+ /**
72
+ * Subscriber for pubsub callback
73
+ */
74
+ const onChangeGroupHandler = useCallback((_msg, data) => {
75
+ if (data && scGroup.id === data.id) {
76
+ setSCGroup(data);
77
+ }
78
+ }, [scGroup, setSCGroup]);
79
+ /**
80
+ * On mount, subscribe to receive groups updates (only edit)
81
+ */
82
+ useEffect(() => {
83
+ if (scGroup) {
84
+ updatesSubscription.current = PubSub.subscribe(`${SCTopicType.GROUP}.${SCEventType.EDIT}`, onChangeGroupHandler);
85
+ }
86
+ return () => {
87
+ updatesSubscription.current && PubSub.unsubscribe(updatesSubscription.current);
88
+ };
89
+ }, [scGroup]);
90
+ /**
91
+ * Loading group
92
+ */
93
+ if (!scGroup) {
94
+ return React.createElement(GroupInfoWidgetSkeleton, null);
95
+ }
65
96
  /**
66
97
  * Renders root object
67
98
  */
@@ -73,25 +104,48 @@ export default function GroupInfoWidget(inProps) {
73
104
  React.createElement(Typography, { component: "div", className: classes.privacy }, scGroup.privacy === SCGroupPrivacyType.PUBLIC ? (React.createElement(React.Fragment, null,
74
105
  React.createElement(Typography, { className: classes.privacyTitle },
75
106
  React.createElement(Icon, null, "public"),
76
- React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.public", defaultMessage: "ui.groupForm.privacy.public" })),
107
+ React.createElement(FormattedMessage, { id: "ui.groupInfoWidget.privacy.public", defaultMessage: "ui.groupInfoWidget.privacy.public" })),
77
108
  React.createElement(Typography, { variant: "body2" },
78
- React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.public.info", defaultMessage: "ui.groupForm.privacy.public.info", values: { b: (chunks) => React.createElement("strong", null, chunks) } })))) : (React.createElement(React.Fragment, null,
109
+ React.createElement(FormattedMessage, { id: "ui.groupInfoWidget.privacy.public.info", defaultMessage: "ui.groupInfoWidget.privacy.public.info", values: {
110
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
111
+ // @ts-ignore
112
+ b: (chunks) => React.createElement("strong", null, chunks)
113
+ } })))) : (React.createElement(React.Fragment, null,
79
114
  React.createElement(Typography, { className: classes.privacyTitle },
80
115
  React.createElement(Icon, null, "private"),
81
- React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.private", defaultMessage: "ui.groupForm.privacy.private" })),
116
+ React.createElement(FormattedMessage, { id: "ui.groupInfoWidget.privacy.private", defaultMessage: "ui.groupInfoWidget.privacy.private" })),
82
117
  React.createElement(Typography, { variant: "body2" },
83
- React.createElement(FormattedMessage, { id: "ui.groupForm.privacy.private.info", defaultMessage: "ui.groupForm.private.public.info", values: { b: (chunks) => React.createElement("strong", null, chunks) } }))))),
118
+ React.createElement(FormattedMessage, { id: "ui.groupInfoWidget.privacy.private.info", defaultMessage: "ui.groupInfoWidget.private.public.info", values: {
119
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
120
+ // @ts-ignore
121
+ b: (chunks) => React.createElement("strong", null, chunks)
122
+ } }))))),
84
123
  scGroup.privacy === SCGroupPrivacyType.PRIVATE && (React.createElement(Typography, { component: "div", className: classes.visibility }, scGroup.visible ? (React.createElement(React.Fragment, null,
85
124
  React.createElement(Typography, { className: classes.visibilityTitle },
86
125
  React.createElement(Icon, null, "visibility"),
87
126
  React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.visible", defaultMessage: "ui.groupForm.visibility.visible" })),
88
127
  React.createElement(Typography, { variant: "body2" },
89
- React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.visible.info", defaultMessage: "ui.groupForm.visibility.visible.info", values: { b: (chunks) => React.createElement("strong", null, chunks) } })))) : (React.createElement(React.Fragment, null,
128
+ React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.visible.info", defaultMessage: "ui.groupForm.visibility.visible.info", values: {
129
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
130
+ // @ts-ignore
131
+ b: (chunks) => React.createElement("strong", null, chunks)
132
+ } })))) : (React.createElement(React.Fragment, null,
90
133
  React.createElement(Typography, { className: classes.visibilityTitle },
91
134
  React.createElement(Icon, null, "visibility_off"),
92
135
  React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.hidden", defaultMessage: "ui.groupForm.visibility.hidden" })),
93
136
  React.createElement(Typography, { variant: "body2" },
94
- React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.hidden.info", defaultMessage: "ui.groupForm.visibility.hidden.info", values: { b: (chunks) => React.createElement("strong", null, chunks) } })))))),
137
+ React.createElement(FormattedMessage, { id: "ui.groupForm.visibility.hidden.info", defaultMessage: "ui.groupForm.visibility.hidden.info", values: {
138
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
139
+ // @ts-ignore
140
+ b: (chunks) => React.createElement("strong", null, chunks)
141
+ } })))))),
95
142
  React.createElement(Typography, { variant: "body2", className: classes.date },
96
- React.createElement(FormattedMessage, { id: "ui.groupInfoWidget.date", defaultMessage: "ui.groupInfoWidget.date", values: { date: intl.formatDate(scGroup.created_at, { day: 'numeric', year: 'numeric', month: 'long' }) } })))));
143
+ React.createElement(FormattedMessage, { id: "ui.groupInfoWidget.date", defaultMessage: "ui.groupInfoWidget.date", values: { date: intl.formatDate(scGroup.created_at, { day: 'numeric', year: 'numeric', month: 'long' }) } })),
144
+ React.createElement(Typography, { variant: "body2", className: classes.admin },
145
+ React.createElement(FormattedMessage, { id: "ui.groupInfoWidget.admin", defaultMessage: "ui.groupInfoWidget.admin", values: {
146
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
147
+ // @ts-ignore
148
+ b: (chunks) => React.createElement("strong", null, chunks),
149
+ admin: scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by.username
150
+ } })))));
97
151
  }