@selfcommunity/react-ui 0.7.9-alpha.7 → 0.7.9-alpha.71

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