@selfcommunity/react-ui 0.8.0-embeds.17 → 0.8.1-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/lib/cjs/components/Categories/Categories.js +22 -0
  2. package/lib/cjs/components/CategoriesPopularWidget/CategoriesPopularWidget.js +21 -0
  3. package/lib/cjs/components/CategoriesSuggestionWidget/CategoriesSuggestionWidget.js +21 -0
  4. package/lib/cjs/components/Composer/TypeSwitchButtonGroup/TypeSwitchButtonGroup.js +1 -1
  5. package/lib/cjs/components/Events/Events.js +15 -5
  6. package/lib/cjs/components/Events/LocationEventsFilter.d.ts +14 -0
  7. package/lib/cjs/components/Events/LocationEventsFilter.js +45 -0
  8. package/lib/cjs/components/Events/PastEventsFilter.js +1 -2
  9. package/lib/cjs/components/Feed/Feed.js +3 -2
  10. package/lib/cjs/components/GroupActionsMenu/index.d.ts +57 -0
  11. package/lib/cjs/components/GroupActionsMenu/index.js +157 -0
  12. package/lib/cjs/components/GroupHeader/GroupHeader.d.ts +6 -0
  13. package/lib/cjs/components/GroupHeader/GroupHeader.js +8 -4
  14. package/lib/cjs/components/Groups/Groups.js +26 -0
  15. package/lib/cjs/components/NavigationMenuIconButton/NavigationMenuDrawer.d.ts +31 -0
  16. package/lib/cjs/components/NavigationMenuIconButton/NavigationMenuDrawer.js +35 -0
  17. package/lib/cjs/components/NavigationMenuIconButton/NavigationMenuIconButton.d.ts +9 -20
  18. package/lib/cjs/components/NavigationMenuIconButton/NavigationMenuIconButton.js +4 -20
  19. package/lib/cjs/components/NavigationMenuIconButton/index.d.ts +2 -1
  20. package/lib/cjs/components/NavigationMenuIconButton/index.js +3 -1
  21. package/lib/cjs/components/NavigationToolbar/NavigationToolbar.d.ts +5 -0
  22. package/lib/cjs/components/NavigationToolbar/NavigationToolbar.js +2 -2
  23. package/lib/cjs/components/OnBoardingWidget/OnBoardingWidget.d.ts +5 -1
  24. package/lib/cjs/components/OnBoardingWidget/OnBoardingWidget.js +55 -7
  25. package/lib/cjs/components/OnBoardingWidget/Steps/Appearance/Appearance.js +8 -4
  26. package/lib/cjs/components/OnBoardingWidget/Steps/Invite/Invite.js +56 -12
  27. package/lib/cjs/components/PlatformWidget/constants.d.ts +0 -4
  28. package/lib/cjs/components/PlatformWidget/constants.js +1 -5
  29. package/lib/cjs/constants/GroupActionsMenu.d.ts +5 -0
  30. package/lib/cjs/constants/GroupActionsMenu.js +8 -0
  31. package/lib/cjs/constants/PubSub.d.ts +8 -1
  32. package/lib/cjs/constants/PubSub.js +9 -1
  33. package/lib/cjs/index.d.ts +4 -2
  34. package/lib/cjs/index.js +11 -5
  35. package/lib/cjs/shared/EventInfoDetails/index.js +3 -3
  36. package/lib/cjs/shared/InfiniteScroll/index.js +4 -4
  37. package/lib/cjs/shared/Media/Link/DisplayComponent.js +5 -5
  38. package/lib/esm/components/Categories/Categories.js +23 -1
  39. package/lib/esm/components/CategoriesPopularWidget/CategoriesPopularWidget.js +22 -1
  40. package/lib/esm/components/CategoriesSuggestionWidget/CategoriesSuggestionWidget.js +22 -1
  41. package/lib/esm/components/Composer/TypeSwitchButtonGroup/TypeSwitchButtonGroup.js +2 -2
  42. package/lib/esm/components/Events/Events.js +16 -6
  43. package/lib/esm/components/Events/LocationEventsFilter.d.ts +14 -0
  44. package/lib/esm/components/Events/LocationEventsFilter.js +41 -0
  45. package/lib/esm/components/Events/PastEventsFilter.js +1 -2
  46. package/lib/esm/components/Feed/Feed.js +4 -3
  47. package/lib/esm/components/GroupActionsMenu/index.d.ts +57 -0
  48. package/lib/esm/components/GroupActionsMenu/index.js +154 -0
  49. package/lib/esm/components/GroupHeader/GroupHeader.d.ts +6 -0
  50. package/lib/esm/components/GroupHeader/GroupHeader.js +9 -5
  51. package/lib/esm/components/Groups/Groups.js +27 -1
  52. package/lib/esm/components/NavigationMenuIconButton/NavigationMenuDrawer.d.ts +31 -0
  53. package/lib/esm/components/NavigationMenuIconButton/NavigationMenuDrawer.js +32 -0
  54. package/lib/esm/components/NavigationMenuIconButton/NavigationMenuIconButton.d.ts +9 -20
  55. package/lib/esm/components/NavigationMenuIconButton/NavigationMenuIconButton.js +6 -22
  56. package/lib/esm/components/NavigationMenuIconButton/index.d.ts +2 -1
  57. package/lib/esm/components/NavigationMenuIconButton/index.js +2 -1
  58. package/lib/esm/components/NavigationToolbar/NavigationToolbar.d.ts +5 -0
  59. package/lib/esm/components/NavigationToolbar/NavigationToolbar.js +2 -2
  60. package/lib/esm/components/OnBoardingWidget/OnBoardingWidget.d.ts +5 -1
  61. package/lib/esm/components/OnBoardingWidget/OnBoardingWidget.js +57 -9
  62. package/lib/esm/components/OnBoardingWidget/Steps/Appearance/Appearance.js +9 -5
  63. package/lib/esm/components/OnBoardingWidget/Steps/Invite/Invite.js +59 -14
  64. package/lib/esm/components/PlatformWidget/constants.d.ts +0 -4
  65. package/lib/esm/components/PlatformWidget/constants.js +0 -4
  66. package/lib/esm/constants/GroupActionsMenu.d.ts +5 -0
  67. package/lib/esm/constants/GroupActionsMenu.js +5 -0
  68. package/lib/esm/constants/PubSub.d.ts +8 -1
  69. package/lib/esm/constants/PubSub.js +8 -0
  70. package/lib/esm/index.d.ts +4 -2
  71. package/lib/esm/index.js +5 -3
  72. package/lib/esm/shared/EventInfoDetails/index.js +3 -3
  73. package/lib/esm/shared/InfiniteScroll/index.js +4 -4
  74. package/lib/esm/shared/Media/Link/DisplayComponent.js +5 -5
  75. package/lib/umd/148.js +2 -0
  76. package/lib/umd/react-ui.js +1 -1
  77. package/package.json +9 -9
  78. package/lib/umd/99.js +0 -2
  79. /package/lib/umd/{99.js.LICENSE.txt → 148.js.LICENSE.txt} +0 -0
@@ -5,7 +5,7 @@ import { styled } from '@mui/material/styles';
5
5
  import { useThemeProps } from '@mui/system';
6
6
  import { Endpoints, http } from '@selfcommunity/api-services';
7
7
  import { SCPreferences, SCPreferencesContext, SCUserContext, UserUtils } from '@selfcommunity/react-core';
8
- import { SCEventDateFilterType, SCEventSubscriptionStatusType } from '@selfcommunity/types';
8
+ import { SCEventDateFilterType, SCEventSubscriptionStatusType, SCEventLocationFilterType } from '@selfcommunity/types';
9
9
  import { Logger } from '@selfcommunity/utils';
10
10
  import classNames from 'classnames';
11
11
  import { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
@@ -19,6 +19,7 @@ import { PREFIX } from './constants';
19
19
  import PastEventsFilter from './PastEventsFilter';
20
20
  import PubSub from 'pubsub-js';
21
21
  import { SCGroupEventType, SCTopicType } from '../../constants/PubSub';
22
+ import LocationEventsFilter from './LocationEventsFilter';
22
23
  const classes = {
23
24
  root: `${PREFIX}-root`,
24
25
  filters: `${PREFIX}-filters`,
@@ -86,6 +87,7 @@ export default function Events(inProps) {
86
87
  const [next, setNext] = useState(null);
87
88
  const [query, setQuery] = useState('');
88
89
  const [dateSearch, setDateSearch] = useState(options[0].value);
90
+ const [location, setLocation] = useState(SCEventLocationFilterType.ANY);
89
91
  const [showFollowed, setShowFollowed] = useState(false);
90
92
  const [showPastEvents, setShowPastEvents] = useState(false);
91
93
  const [showMyEvents, setShowMyEvents] = useState(false);
@@ -125,7 +127,7 @@ export default function Events(inProps) {
125
127
  url: endpoint.url({}),
126
128
  method: endpoint.method,
127
129
  params: Object.assign(Object.assign({}, endpointQueryParams), (general
128
- ? Object.assign(Object.assign(Object.assign(Object.assign({}, (search && { search: query })), (dateSearch !== SCEventDateFilterType.ANY && { date_filter: dateSearch })), (showFollowed && { follows: showFollowed })), (showPastEvents && { date_filter: SCEventDateFilterType.PAST })) : Object.assign(Object.assign({ subscription_status: SCEventSubscriptionStatusType.GOING }, (showPastEvents && { past: showPastEvents })), (showMyEvents && { created_by: authUserId }))))
130
+ ? Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (search && { search: query })), (dateSearch !== SCEventDateFilterType.ANY && { date_filter: dateSearch })), (location !== SCEventLocationFilterType.ANY && { location })), (showFollowed && { follows: showFollowed })), (showPastEvents && { date_filter: SCEventDateFilterType.PAST })) : Object.assign(Object.assign(Object.assign({ subscription_status: SCEventSubscriptionStatusType.GOING }, (location !== SCEventLocationFilterType.ANY && { location })), (showPastEvents && { past: showPastEvents })), (showMyEvents && { created_by: authUserId }))))
129
131
  })
130
132
  .then((res) => {
131
133
  setEvents(res.data.results);
@@ -146,7 +148,7 @@ export default function Events(inProps) {
146
148
  else {
147
149
  query === '' && fetchEvents();
148
150
  }
149
- }, [contentAvailability, dateSearch, showFollowed, showPastEvents, showMyEvents, query]);
151
+ }, [contentAvailability, dateSearch, location, showFollowed, showPastEvents, showMyEvents, query]);
150
152
  /**
151
153
  * Subscriber for pubsub callback
152
154
  */
@@ -199,10 +201,18 @@ export default function Events(inProps) {
199
201
  const handleOnChangeTimeFrame = (event) => {
200
202
  setDateSearch(event.target.value);
201
203
  };
204
+ /**
205
+ * Handle change location
206
+ * @param event
207
+ */
208
+ const handleOnChangeLocation = (event) => {
209
+ setLocation(event.target.value);
210
+ };
202
211
  /**
203
212
  * Renders events list
204
213
  */
205
- const c = (_jsxs(_Fragment, { children: [showFilters && (_jsx(Grid, Object.assign({ container: true, className: classes.filters, gap: 2 }, { children: filters ? (filters) : !general ? (_jsxs(_Fragment, { children: [_jsx(Grid, Object.assign({ item: true }, { children: _jsx(PastEventsFilter, { showPastEvents: showPastEvents, handleClick: handleChipPastClick, handleDeleteClick: handleDeletePastClick, autoHide: !events.length && !showPastEvents, disabled: loading }) })), (events.length !== 0 || (events.length === 0 && showMyEvents)) && (_jsx(Grid, Object.assign({ item: true }, { children: _jsx(EventsChipRoot
214
+ console.log(location);
215
+ const c = (_jsxs(_Fragment, { children: [showFilters && (_jsx(Grid, Object.assign({ container: true, className: classes.filters, gap: 2 }, { children: filters ? (filters) : !general ? (_jsxs(_Fragment, { children: [(events.length !== 0 || (events.length === 0 && showMyEvents)) && (_jsx(Grid, Object.assign({ item: true }, { children: _jsx(EventsChipRoot
206
216
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
207
217
  // @ts-ignore
208
218
  , {
@@ -214,14 +224,14 @@ export default function Events(inProps) {
214
224
  variant: showMyEvents ? 'filled' : 'outlined', label: _jsx(FormattedMessage, { id: "ui.events.filterByCreatedByMe", defaultMessage: "ui.events.filterByCreatedByMe" }), onClick: () => setShowMyEvents(!showMyEvents),
215
225
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
216
226
  // @ts-ignore
217
- showFollowed: showMyEvents, deleteIcon: showMyEvents ? _jsx(Icon, { children: "close" }) : null, onDelete: showMyEvents ? handleDeleteClick : null, disabled: loading }) })))] })) : (_jsxs(_Fragment, { children: [_jsx(Grid, Object.assign({ item: true, xs: 12, md: 4 }, { children: _jsx(TextField, { className: classes.search, size: 'small', fullWidth: true, value: query, label: _jsx(FormattedMessage, { id: "ui.events.filterByName", defaultMessage: "ui.events.filterByName" }), variant: "outlined", onChange: handleOnChangeFilterName, disabled: loading || (!events.length && !query), onKeyUp: (e) => {
227
+ showFollowed: showMyEvents, deleteIcon: showMyEvents ? _jsx(Icon, { children: "close" }) : null, onDelete: showMyEvents ? handleDeleteClick : null, autoHide: !loading && !events.length, disabled: loading }) }))), _jsx(Grid, Object.assign({ item: true }, { children: _jsx(PastEventsFilter, { showPastEvents: showPastEvents, handleClick: handleChipPastClick, handleDeleteClick: handleDeletePastClick, autoHide: !loading && !events.length && !showPastEvents, disabled: loading }) })), _jsx(Grid, Object.assign({ item: true, xs: 12, md: 2 }, { children: _jsx(LocationEventsFilter, { value: location, autoHide: !loading && !events.length, disabled: loading || (!events.length && !location), handleOnChange: handleOnChangeLocation }) }))] })) : (_jsxs(_Fragment, { children: [_jsx(Grid, Object.assign({ item: true, xs: 12, md: 3 }, { children: _jsx(TextField, { className: classes.search, size: 'small', fullWidth: true, value: query, label: _jsx(FormattedMessage, { id: "ui.events.filterByName", defaultMessage: "ui.events.filterByName" }), variant: "outlined", onChange: handleOnChangeFilterName, disabled: loading || (!events.length && !query), onKeyUp: (e) => {
218
228
  e.preventDefault();
219
229
  if (e.key === 'Enter') {
220
230
  fetchEvents(true);
221
231
  }
222
232
  }, InputProps: {
223
233
  endAdornment: (_jsx(InputAdornment, Object.assign({ position: "end" }, { children: isMobile ? (_jsx(IconButton, Object.assign({ onClick: () => fetchEvents(true), disabled: loading || (!events.length && !query) }, { children: _jsx(Icon, { children: "search" }) }))) : (_jsx(Button, { size: "small", variant: "contained", color: "secondary", onClick: () => fetchEvents(true), endIcon: _jsx(Icon, { children: "search" }), disabled: loading || (!events.length && !query) })) })))
224
- } }) })), _jsx(Grid, Object.assign({ item: true, xs: 12, md: 2 }, { children: _jsxs(FormControl, Object.assign({ fullWidth: true }, { children: [_jsx(InputLabel, { children: _jsx(FormattedMessage, { id: "ui.events.filterByDate", defaultMessage: "ui.events.filterByDate" }) }), _jsx(Select, Object.assign({ disabled: showPastEvents || loading || (!events.length && dateSearch === SCEventDateFilterType.ANY), size: 'small', label: _jsx(FormattedMessage, { id: "ui.events.filterByDate", defaultMessage: "ui.events.filterByDate" }), value: dateSearch, onChange: handleOnChangeTimeFrame, renderValue: (selected) => options.find((option) => option.value === selected).label }, { children: options.map((option) => (_jsxs(MenuItem, Object.assign({ value: option.value }, { children: [_jsx(Radio, { checked: dateSearch === option.value, value: option.value, name: "radio-button-select", inputProps: { 'aria-label': option.label } }), option.label] }), option.value))) }))] })) })), authUserId && (_jsx(Grid, Object.assign({ item: true }, { children: _jsx(EventsChipRoot
234
+ } }) })), _jsx(Grid, Object.assign({ item: true, xs: 12, md: 2 }, { children: _jsxs(FormControl, Object.assign({ fullWidth: true }, { children: [_jsx(InputLabel, { children: _jsx(FormattedMessage, { id: "ui.events.filterByDate", defaultMessage: "ui.events.filterByDate" }) }), _jsx(Select, Object.assign({ disabled: showPastEvents || loading || (!events.length && dateSearch === SCEventDateFilterType.ANY), size: 'small', label: _jsx(FormattedMessage, { id: "ui.events.filterByDate", defaultMessage: "ui.events.filterByDate" }), value: dateSearch, onChange: handleOnChangeTimeFrame, renderValue: (selected) => options.find((option) => option.value === selected).label }, { children: options.map((option) => (_jsxs(MenuItem, Object.assign({ value: option.value }, { children: [_jsx(Radio, { checked: dateSearch === option.value, value: option.value, name: "radio-button-select", inputProps: { 'aria-label': option.label } }), option.label] }), option.value))) }))] })) })), _jsx(Grid, Object.assign({ item: true, xs: 12, md: 2 }, { children: _jsx(LocationEventsFilter, { value: location, disabled: loading || (!events.length && !location), handleOnChange: handleOnChangeLocation }) })), authUserId && (_jsx(Grid, Object.assign({ item: true }, { children: _jsx(EventsChipRoot
225
235
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
226
236
  // @ts-ignore
227
237
  , {
@@ -0,0 +1,14 @@
1
+ import { ChipProps } from '@mui/material';
2
+ import { SCEventLocationFilterType } from '@selfcommunity/types';
3
+ export interface LocationEventsFilterProps extends ChipProps {
4
+ /**
5
+ * Overrides or extends the styles applied to the component.
6
+ * @default null
7
+ */
8
+ className?: string;
9
+ value: SCEventLocationFilterType;
10
+ disabled?: boolean;
11
+ autoHide?: boolean;
12
+ handleOnChange: (event: any) => void;
13
+ }
14
+ export default function LocationEventsFilter(inProps: LocationEventsFilterProps): JSX.Element;
@@ -0,0 +1,41 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { FormControl, InputLabel, MenuItem, Radio, Select } from '@mui/material';
3
+ import { FormattedMessage } from 'react-intl';
4
+ import { useThemeProps } from '@mui/system';
5
+ import { PREFIX } from './constants';
6
+ import { styled } from '@mui/material/styles';
7
+ import { SCEventLocationFilterType } from '@selfcommunity/types';
8
+ import classNames from 'classnames';
9
+ const classes = {
10
+ root: `${PREFIX}-root`
11
+ };
12
+ const Root = styled(FormControl, {
13
+ name: PREFIX,
14
+ slot: 'Root'
15
+ })(() => ({}));
16
+ const locationOptions = [
17
+ {
18
+ value: SCEventLocationFilterType.ANY,
19
+ label: _jsx(FormattedMessage, { id: "ui.events.location.select.any", defaultMessage: "ui.events.location.select.any" })
20
+ },
21
+ {
22
+ value: SCEventLocationFilterType.PERSON,
23
+ label: _jsx(FormattedMessage, { id: "ui.eventInfoDetails.location.inPerson", defaultMessage: "ui.eventInfoDetails.location.inPerson" })
24
+ },
25
+ {
26
+ value: SCEventLocationFilterType.ONLINE,
27
+ label: _jsx(FormattedMessage, { id: "ui.eventInfoDetails.location.virtual", defaultMessage: "ui.eventInfoDetails.location.virtual" })
28
+ }
29
+ ];
30
+ export default function LocationEventsFilter(inProps) {
31
+ // PROPS
32
+ const props = useThemeProps({
33
+ props: inProps,
34
+ name: PREFIX
35
+ });
36
+ const { className, value, disabled = false, autoHide = false, handleOnChange } = props;
37
+ if (autoHide) {
38
+ return null;
39
+ }
40
+ return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className), fullWidth: true }, { children: [_jsx(InputLabel, { children: _jsx(FormattedMessage, { id: "ui.events.filterByLocation", defaultMessage: "ui.events.filterByLocation" }) }), _jsx(Select, Object.assign({ disabled: disabled, size: 'small', label: _jsx(FormattedMessage, { id: "ui.events.location", defaultMessage: "ui.events.location" }), value: value, onChange: handleOnChange, renderValue: (selected) => locationOptions.find((option) => option.value === selected).label }, { children: locationOptions.map((option) => (_jsxs(MenuItem, Object.assign({ value: option.value }, { children: [_jsx(Radio, { checked: value === option.value, value: option.value, name: "radio-button-select", inputProps: { 'aria-label': option.label } }), option.label] }), option.value))) }))] })));
41
+ }
@@ -5,7 +5,6 @@ import { FormattedMessage } from 'react-intl';
5
5
  import { useThemeProps } from '@mui/system';
6
6
  import { PREFIX } from './constants';
7
7
  import { EventsChipRoot } from './Events';
8
- import HiddenPlaceholder from '../../shared/HiddenPlaceholder';
9
8
  export default function PastEventsFilter(inProps) {
10
9
  // PROPS
11
10
  const props = useThemeProps({
@@ -14,7 +13,7 @@ export default function PastEventsFilter(inProps) {
14
13
  });
15
14
  const { autoHide = false, showPastEvents, handleClick, handleDeleteClick } = props, rest = __rest(props, ["autoHide", "showPastEvents", "handleClick", "handleDeleteClick"]);
16
15
  if (autoHide) {
17
- return _jsx(HiddenPlaceholder, {});
16
+ return null;
18
17
  }
19
18
  return (_jsx(EventsChipRoot
20
19
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
@@ -3,7 +3,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-run
3
3
  import React, { forwardRef, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from 'react';
4
4
  import { Link, SCCache, SCPreferences, SCPreferencesContext, SCUserContext, useIsComponentMountedRef, usePreviousValue, useSCFetchFeed } from '@selfcommunity/react-core';
5
5
  import { styled, useTheme } from '@mui/material/styles';
6
- import { Box, CardContent, Grid, Hidden, Typography, useMediaQuery } from '@mui/material';
6
+ import { Box, Button, CardContent, Grid, Hidden, Typography, useMediaQuery } from '@mui/material';
7
7
  import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
8
8
  import { GenericSkeleton } from '../Skeleton';
9
9
  import CustomAdv from '../CustomAdv';
@@ -34,6 +34,7 @@ const classes = {
34
34
  left: `${PREFIX}-left`,
35
35
  leftItems: `${PREFIX}-left-items`,
36
36
  start: `${PREFIX}-start`,
37
+ headerItem: `${PREFIX}-header-item`,
37
38
  end: `${PREFIX}-end`,
38
39
  endMessage: `${PREFIX}-end-message`,
39
40
  right: `${PREFIX}-right`,
@@ -290,7 +291,7 @@ const Feed = (inProps, ref) => {
290
291
  const renderHeaderComponent = () => {
291
292
  return (_jsx(Box, Object.assign({ className: classes.start }, { children: !feedDataObject.previous && (_jsxs(_Fragment, { children: [virtualScrollerMountState.current && HeaderComponent, headData.map((item) => {
292
293
  const _itemId = `item_${itemIdGenerator(item)}`;
293
- return (_jsx(ItemComponent, Object.assign({ id: _itemId }, itemPropsGenerator(scUserContext.user, item), ItemProps, { sx: { width: '100%' } }), _itemId));
294
+ return (_jsx(ItemComponent, Object.assign({ className: classes.headerItem, id: _itemId }, itemPropsGenerator(scUserContext.user, item), ItemProps, { sx: { width: '100%' } }), _itemId));
294
295
  })] })) })));
295
296
  };
296
297
  /**
@@ -416,6 +417,6 @@ const Feed = (inProps, ref) => {
416
417
  if (feedDataObject.isLoadingNext && !feedDataLeft.length) {
417
418
  return (_jsx(FeedSkeleton, { children: [...Array(3)].map((v, i) => (_jsx(ItemSkeleton, Object.assign({}, ItemSkeletonProps), i))) }));
418
419
  }
419
- return (_jsxs(Root, Object.assign({ container: true, spacing: 2, id: id, className: classNames(classes.root, className) }, { children: [advEnabled && !hideAdvs && enabledCustomAdvPositions.includes(SCCustomAdvPosition.POSITION_BELOW_TOPBAR) ? (_jsx(Grid, Object.assign({ item: true, xs: 12 }, { children: _jsx(CustomAdv, Object.assign({ position: SCCustomAdvPosition.POSITION_BELOW_TOPBAR }, CustomAdvProps)) }))) : null, _jsx(Grid, Object.assign({ item: true, xs: 12, md: 7 }, { children: _jsxs(InfiniteScroll, Object.assign({ ref: containerRef, className: classes.left, dataLength: feedDataLeft.length, next: getNextPage, previous: getPreviousPage, hasMoreNext: Boolean(feedDataObject.next), hasMorePrevious: Boolean(feedDataObject.previous), header: PreviousPageLink, footer: NextPageLink, loaderNext: _jsx(ItemSkeleton, Object.assign({}, ItemSkeletonProps)), loaderPrevious: _jsx(ItemSkeleton, Object.assign({}, ItemSkeletonProps)), scrollThreshold: '90%', endMessage: _jsxs(Box, Object.assign({ className: classes.end }, { children: [_jsx(Widget, Object.assign({ className: classes.endMessage }, { children: _jsx(CardContent, { children: endMessage }) })), FooterComponent ? _jsx(FooterComponent, Object.assign({}, FooterComponentProps)) : null] })), refreshFunction: refresh, pullDownToRefresh: true, pullDownToRefreshThreshold: 1000, pullDownToRefreshContent: null, releaseToRefreshContent: _jsx(Widget, Object.assign({ variant: "outlined", className: classes.refresh }, { children: _jsx(CardContent, { children: refreshMessage }) })), style: { overflow: 'visible' } }, (scrollableTargetId && { scrollableTarget: scrollableTargetId }), { children: [renderHeaderComponent(), feedDataObject.count === 0 && emptyFeedPlaceholder && emptyFeedPlaceholder, _jsx(VirtualizedScroller, Object.assign({ className: classes.leftItems, items: feedDataLeft, itemComponent: InnerItem, onMount: onScrollerMount, onScrollerStateChange: onScrollerStateChange, getItemId: getScrollItemId, preserveScrollPosition: true, preserveScrollPositionOnPrependItems: true, cacheScrollStateKey: SCCache.getVirtualizedScrollStateCacheKey(id), cacheScrollerPositionKey: SCCache.getFeedSPCacheKey(id), cacheStrategy: cacheStrategy }, (scrollableTargetId && { getScrollableContainer: () => document.getElementById(scrollableTargetId) }), VirtualizedScrollerProps))] })) })), feedDataRight.length > 0 && !hideAdvs && (_jsx(Hidden, Object.assign({ smDown: true }, { children: _jsx(Grid, Object.assign({ item: true, xs: 12, md: 5 }, { children: _jsx(StickyBoxComp, Object.assign({ className: classes.right }, FeedSidebarProps, { children: _jsx(React.Suspense, Object.assign({ fallback: _jsx(GenericSkeleton, {}) }, { children: feedDataRight.map((d, i) => (_jsx(d.component, Object.assign({}, d.componentProps), i))) })) })) })) })))] })));
420
+ return (_jsxs(Root, Object.assign({ container: true, spacing: 2, id: id, className: classNames(classes.root, className) }, { children: [advEnabled && !hideAdvs && enabledCustomAdvPositions.includes(SCCustomAdvPosition.POSITION_BELOW_TOPBAR) ? (_jsx(Grid, Object.assign({ item: true, xs: 12 }, { children: _jsx(CustomAdv, Object.assign({ position: SCCustomAdvPosition.POSITION_BELOW_TOPBAR }, CustomAdvProps)) }))) : null, _jsx(Grid, Object.assign({ item: true, xs: 12, md: 7 }, { children: _jsxs(InfiniteScroll, Object.assign({ ref: containerRef, className: classes.left, dataLength: feedDataLeft.length, next: getNextPage, previous: getPreviousPage, hasMoreNext: Boolean(feedDataObject.next), hasMorePrevious: Boolean(feedDataObject.previous), header: PreviousPageLink, footer: NextPageLink, loaderNext: _jsx(ItemSkeleton, Object.assign({}, ItemSkeletonProps)), loaderPrevious: _jsx(ItemSkeleton, Object.assign({}, ItemSkeletonProps)), scrollThreshold: '90%', endMessage: _jsxs(Box, Object.assign({ className: classes.end }, { children: [_jsx(Widget, Object.assign({ className: classes.endMessage }, { children: _jsx(CardContent, { children: endMessage }) })), FooterComponent ? _jsx(FooterComponent, Object.assign({}, FooterComponentProps)) : null] })), refreshFunction: refresh, pullDownToRefresh: true, pullDownToRefreshThreshold: 1000, pullDownToRefreshContent: null, releaseToRefreshContent: _jsx(Button, Object.assign({ color: "secondary", variant: "contained", className: classes.refresh }, { children: refreshMessage })), style: { overflow: 'visible' } }, (scrollableTargetId && { scrollableTarget: scrollableTargetId }), { children: [renderHeaderComponent(), feedDataObject.count === 0 && emptyFeedPlaceholder && emptyFeedPlaceholder, _jsx(VirtualizedScroller, Object.assign({ className: classes.leftItems, items: feedDataLeft, itemComponent: InnerItem, onMount: onScrollerMount, onScrollerStateChange: onScrollerStateChange, getItemId: getScrollItemId, preserveScrollPosition: true, preserveScrollPositionOnPrependItems: true, cacheScrollStateKey: SCCache.getVirtualizedScrollStateCacheKey(id), cacheScrollerPositionKey: SCCache.getFeedSPCacheKey(id), cacheStrategy: cacheStrategy }, (scrollableTargetId && { getScrollableContainer: () => document.getElementById(scrollableTargetId) }), VirtualizedScrollerProps))] })) })), feedDataRight.length > 0 && !hideAdvs && (_jsx(Hidden, Object.assign({ smDown: true }, { children: _jsx(Grid, Object.assign({ item: true, xs: 12, md: 5 }, { children: _jsx(StickyBoxComp, Object.assign({ className: classes.right }, FeedSidebarProps, { children: _jsx(React.Suspense, Object.assign({ fallback: _jsx(GenericSkeleton, {}) }, { children: feedDataRight.map((d, i) => (_jsx(d.component, Object.assign({}, d.componentProps), i))) })) })) })) })))] })));
420
421
  };
421
422
  export default forwardRef(Feed);
@@ -0,0 +1,57 @@
1
+ import { IconButtonProps } from '@mui/material';
2
+ import { SCGroupType } from '@selfcommunity/types';
3
+ export interface GroupActionsMenuProps extends IconButtonProps {
4
+ /**
5
+ * Overrides or extends the styles applied to the component.
6
+ * @default null
7
+ */
8
+ className?: string;
9
+ /**
10
+ * The group
11
+ */
12
+ group: SCGroupType;
13
+ /**
14
+ * The group id
15
+ */
16
+ groupId?: number;
17
+ /**
18
+ * Handles callback on delete confirm
19
+ */
20
+ onDeleteConfirm?: () => void;
21
+ /**
22
+ * Handles on edit success
23
+ */
24
+ onEditSuccess?: (data: SCGroupType) => any;
25
+ /**
26
+ * Any other properties
27
+ */
28
+ [p: string]: any;
29
+ }
30
+ /**
31
+ * > API documentation for the Community-JS GroupActionsMenu component. Learn about the available props and the CSS API.
32
+
33
+ #### Import
34
+
35
+ ```jsx
36
+ import {GroupActionsMenu} from '@selfcommunity/react-ui';
37
+ ```
38
+
39
+ #### Component Name
40
+
41
+ The name `SCGroupActionsMenu` can be used when providing style overrides in the theme.
42
+
43
+
44
+ #### CSS
45
+
46
+ |Rule Name|Global class|Description|
47
+ |---|---|---|
48
+ |root|.SCGroupActionsMenu-root|Styles applied to the root element.|
49
+ |drawerRoot|.SCGroupActionsMenu-drawer-root|Styles applied to the drawer root element.|
50
+ |menuRoot|.SCGroupActionsMenu-menu-root|Styles applied to the menu root element.|
51
+ |paper|.SCGroupActionsMenu-paper|Styles applied to the paper element.|
52
+ |item|.SCGroupActionsMenu-item|Styles applied to the item element.|
53
+
54
+
55
+ * @param inProps
56
+ */
57
+ export default function GroupActionsMenu(inProps: GroupActionsMenuProps): JSX.Element;
@@ -0,0 +1,154 @@
1
+ import { __rest } from "tslib";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useMemo, useState } from 'react';
4
+ import { styled } from '@mui/material/styles';
5
+ import { Divider, IconButton, List, ListItemIcon, Menu, MenuItem, SwipeableDrawer, useMediaQuery, useTheme } from '@mui/material';
6
+ import { FormattedMessage } from 'react-intl';
7
+ import Icon from '@mui/material/Icon';
8
+ import classNames from 'classnames';
9
+ import { useThemeProps } from '@mui/system';
10
+ import { SCRoutes, useSCFetchGroup, useSCRouting, useSCUser } from '@selfcommunity/react-core';
11
+ import ConfirmDialog from '../../shared/ConfirmDialog/ConfirmDialog';
12
+ import { GroupService } from '@selfcommunity/api-services';
13
+ import { copyTextToClipboard } from '@selfcommunity/utils';
14
+ import { enqueueSnackbar } from 'notistack';
15
+ import PubSub from 'pubsub-js';
16
+ import { SCGroupEventType, SCTopicType } from '../../constants/PubSub';
17
+ import GroupForm from '../../components/GroupForm';
18
+ import { DELETE_GROUP, GET_GROUP_LINK } from '../../constants/GroupActionsMenu';
19
+ const PREFIX = 'SCGroupActionsMenu';
20
+ const classes = {
21
+ root: `${PREFIX}-root`,
22
+ drawerRoot: `${PREFIX}-drawer-root`,
23
+ menuRoot: `${PREFIX}-menu-root`,
24
+ paper: `${PREFIX}-paper`,
25
+ item: `${PREFIX}-item`
26
+ };
27
+ const Root = styled(IconButton, {
28
+ name: PREFIX,
29
+ slot: 'Root'
30
+ })(() => ({}));
31
+ const SwipeableDrawerRoot = styled(SwipeableDrawer, {
32
+ name: PREFIX,
33
+ slot: 'DrawerRoot'
34
+ })(() => ({}));
35
+ const MenuRoot = styled(Menu, {
36
+ name: PREFIX,
37
+ slot: 'MenuRoot'
38
+ })(() => ({}));
39
+ /**
40
+ * > API documentation for the Community-JS GroupActionsMenu component. Learn about the available props and the CSS API.
41
+
42
+ #### Import
43
+
44
+ ```jsx
45
+ import {GroupActionsMenu} from '@selfcommunity/react-ui';
46
+ ```
47
+
48
+ #### Component Name
49
+
50
+ The name `SCGroupActionsMenu` can be used when providing style overrides in the theme.
51
+
52
+
53
+ #### CSS
54
+
55
+ |Rule Name|Global class|Description|
56
+ |---|---|---|
57
+ |root|.SCGroupActionsMenu-root|Styles applied to the root element.|
58
+ |drawerRoot|.SCGroupActionsMenu-drawer-root|Styles applied to the drawer root element.|
59
+ |menuRoot|.SCGroupActionsMenu-menu-root|Styles applied to the menu root element.|
60
+ |paper|.SCGroupActionsMenu-paper|Styles applied to the paper element.|
61
+ |item|.SCGroupActionsMenu-item|Styles applied to the item element.|
62
+
63
+
64
+ * @param inProps
65
+ */
66
+ export default function GroupActionsMenu(inProps) {
67
+ var _a;
68
+ // PROPS
69
+ const props = useThemeProps({
70
+ props: inProps,
71
+ name: PREFIX
72
+ });
73
+ const { className, group, groupId, onDeleteConfirm, onEditSuccess } = props, rest = __rest(props, ["className", "group", "groupId", "onDeleteConfirm", "onEditSuccess"]);
74
+ // STATE
75
+ const [anchorEl, setAnchorEl] = useState(null);
76
+ const [openConfirmDialog, setOpenConfirmDialog] = useState(false);
77
+ const [openEdit, setOpenEdit] = useState(false);
78
+ // HOOKS
79
+ const theme = useTheme();
80
+ const isMobile = useMediaQuery(theme.breakpoints.down('md'));
81
+ const scRoutingContext = useSCRouting();
82
+ const scUserContext = useSCUser();
83
+ const { scGroup, setSCGroup } = useSCFetchGroup({ id: groupId, group });
84
+ 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]);
85
+ // HANDLERS
86
+ const handleOpen = (group) => {
87
+ setAnchorEl(group.currentTarget);
88
+ };
89
+ const handleClose = () => {
90
+ setAnchorEl(null);
91
+ };
92
+ const handleEditClick = () => {
93
+ setOpenEdit((o) => !o);
94
+ };
95
+ const handleCloseDialog = () => {
96
+ setOpenConfirmDialog(false);
97
+ setAnchorEl(null);
98
+ };
99
+ const handleEditSuccess = (data) => {
100
+ setSCGroup(data);
101
+ onEditSuccess && onEditSuccess(data);
102
+ };
103
+ /**
104
+ * Handles thread deletion
105
+ */
106
+ function handleDeleteThread() {
107
+ GroupService.deleteGroup(scGroup.id)
108
+ .then(() => {
109
+ onDeleteConfirm();
110
+ handleCloseDialog();
111
+ PubSub.publish(`${SCTopicType.GROUP}.${SCGroupEventType.DELETE}`, scGroup.id);
112
+ })
113
+ .catch((error) => {
114
+ setOpenConfirmDialog(false);
115
+ console.log(error);
116
+ });
117
+ }
118
+ /**
119
+ * Handles actions
120
+ */
121
+ function handleAction(action) {
122
+ if (action === GET_GROUP_LINK) {
123
+ copyTextToClipboard(`${location.protocol}//${location.host}${scRoutingContext.url(SCRoutes.GROUP_ROUTE_NAME, scGroup)}`).then(() => {
124
+ enqueueSnackbar(_jsx(FormattedMessage, { id: "ui.common.permanentLinkCopied", defaultMessage: "ui.common.permanentLinkCopied" }), {
125
+ variant: 'success',
126
+ autoHideDuration: 3000
127
+ });
128
+ });
129
+ handleClose();
130
+ }
131
+ else if (action === DELETE_GROUP) {
132
+ setOpenConfirmDialog(true);
133
+ handleClose();
134
+ }
135
+ }
136
+ /**
137
+ *
138
+ */
139
+ const renderList = () => {
140
+ return [
141
+ _jsxs(MenuItem, Object.assign({ className: classes.item, onClick: () => handleAction(GET_GROUP_LINK) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "link" }) }), _jsx(FormattedMessage, { id: "ui.groupActionsMenu.item.link", defaultMessage: "ui.groupActionsMenu.item.link" })] }), "link"),
142
+ isGroupAdmin &&
143
+ scGroup.active && [
144
+ _jsx(Divider, {}, "divider"),
145
+ isMobile && (_jsxs(MenuItem, Object.assign({ className: classes.item, onClick: handleEditClick }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "edit" }) }), _jsx(FormattedMessage, { id: "ui.groupActionsMenu.item.edit", defaultMessage: "ui.groupActionsMenu.item.edit" })] }), "edit")),
146
+ _jsxs(MenuItem, Object.assign({ className: classes.item, onClick: () => handleAction(DELETE_GROUP) }, { children: [_jsx(ListItemIcon, { children: _jsx(Icon, { children: "delete" }) }), _jsx(FormattedMessage, { id: "ui.groupActionsMenu.item.delete", defaultMessage: "ui.groupActionsMenu.item.delete" })] }), "delete")
147
+ ]
148
+ ];
149
+ };
150
+ if (!scGroup) {
151
+ return null;
152
+ }
153
+ return (_jsxs(_Fragment, { children: [_jsx(Root, Object.assign({ className: classNames(classes.root, className) }, rest, { onClick: handleOpen }, { children: _jsx(Icon, { children: "more_vert" }) })), isMobile ? (_jsx(SwipeableDrawerRoot, Object.assign({ className: classes.drawerRoot, anchor: "bottom", open: Boolean(anchorEl), onClose: handleClose, onOpen: handleOpen, PaperProps: { className: classes.paper }, disableSwipeToOpen: true }, { children: _jsx(List, { children: renderList() }) }))) : (_jsx(MenuRoot, Object.assign({ className: classes.menuRoot, anchorEl: anchorEl, open: Boolean(anchorEl), onClose: handleClose, PaperProps: { className: classes.paper } }, { children: renderList() }))), openConfirmDialog && (_jsx(ConfirmDialog, { open: openConfirmDialog, title: _jsx(FormattedMessage, { id: "ui.groupActionsMenu.dialog.msg", defaultMessage: "ui.groupActionsMenu.dialog.msg" }), btnConfirm: _jsx(FormattedMessage, { id: "ui.groupActionsMenu.dialog.confirm", defaultMessage: "ui.groupActionsMenu.dialog.confirm" }), onConfirm: handleDeleteThread, onClose: handleCloseDialog })), openEdit && _jsx(GroupForm, { onClose: handleEditClick, group: scGroup, onSuccess: handleEditSuccess })] }));
154
+ }
@@ -3,6 +3,7 @@ import { ChangeGroupCoverProps } from '../ChangeGroupCover';
3
3
  import { ChangeGroupPictureProps } from '../ChangeGroupPicture';
4
4
  import { GroupMembersButtonProps } from '../GroupMembersButton';
5
5
  import { GroupSubscribeButtonProps } from '../GroupSubscribeButton';
6
+ import { GroupActionsMenuProps } from '../GroupActionsMenu';
6
7
  export interface GroupHeaderProps {
7
8
  /**
8
9
  * Id of group object
@@ -44,6 +45,11 @@ export interface GroupHeaderProps {
44
45
  * @default {}
45
46
  */
46
47
  GroupMembersButtonProps?: GroupMembersButtonProps;
48
+ /**
49
+ * Props to spread event actions menu
50
+ * @default {}
51
+ */
52
+ GroupActionsProps?: Omit<GroupActionsMenuProps, 'group'>;
47
53
  /**
48
54
  * Any other properties
49
55
  */
@@ -2,7 +2,7 @@ import { __rest } from "tslib";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import { useCallback, useEffect, useMemo, useRef } from 'react';
4
4
  import { styled } from '@mui/material/styles';
5
- import { Avatar, Box, Icon, Paper, Typography } from '@mui/material';
5
+ import { Avatar, Box, Icon, Paper, Typography, useMediaQuery, useTheme } from '@mui/material';
6
6
  import { SCGroupPrivacyType, SCGroupSubscriptionStatusType } from '@selfcommunity/types';
7
7
  import { SCPreferences, useSCFetchGroup, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
8
8
  import GroupHeaderSkeleton from './Skeleton';
@@ -19,6 +19,7 @@ import GroupSubscribeButton from '../GroupSubscribeButton';
19
19
  import GroupInviteButton from '../GroupInviteButton';
20
20
  import { SCGroupEventType, SCTopicType } from '../../constants/PubSub';
21
21
  import PubSub from 'pubsub-js';
22
+ import GroupActionsMenu from '../GroupActionsMenu';
22
23
  const classes = {
23
24
  root: `${PREFIX}-root`,
24
25
  cover: `${PREFIX}-cover`,
@@ -30,7 +31,8 @@ const classes = {
30
31
  visibility: `${PREFIX}-visibility`,
31
32
  visibilityItem: `${PREFIX}-visibility-item`,
32
33
  members: `${PREFIX}-members`,
33
- membersCounter: `${PREFIX}-members-counter`
34
+ membersCounter: `${PREFIX}-members-counter`,
35
+ multiActions: `${PREFIX}-multi-actions`
34
36
  };
35
37
  const Root = styled(Box, {
36
38
  name: PREFIX,
@@ -74,7 +76,7 @@ export default function GroupHeader(inProps) {
74
76
  props: inProps,
75
77
  name: PREFIX
76
78
  });
77
- const { id = null, className = null, group, groupId = null, ChangePictureProps = {}, ChangeCoverProps = {}, GroupSubscribeButtonProps = {}, GroupMembersButtonProps = {} } = props, rest = __rest(props, ["id", "className", "group", "groupId", "ChangePictureProps", "ChangeCoverProps", "GroupSubscribeButtonProps", "GroupMembersButtonProps"]);
79
+ const { id = null, className = null, group, groupId = null, ChangePictureProps = {}, ChangeCoverProps = {}, GroupSubscribeButtonProps = {}, GroupMembersButtonProps = {}, GroupActionsProps } = props, rest = __rest(props, ["id", "className", "group", "groupId", "ChangePictureProps", "ChangeCoverProps", "GroupSubscribeButtonProps", "GroupMembersButtonProps", "GroupActionsProps"]);
78
80
  // PREFERENCES
79
81
  const scPreferences = useSCPreferences();
80
82
  const visibilityEnabled = useMemo(() => scPreferences.preferences[SCPreferences.CONFIGURATIONS_GROUPS_VISIBILITY_ENABLED].value, [scPreferences.preferences]);
@@ -83,6 +85,8 @@ export default function GroupHeader(inProps) {
83
85
  const scUserContext = useSCUser();
84
86
  // HOOKS
85
87
  const { scGroup, setSCGroup } = useSCFetchGroup({ id: groupId, group });
88
+ const theme = useTheme();
89
+ const isMobile = useMediaQuery(theme.breakpoints.down('md'));
86
90
  // REFS
87
91
  const updatesSubscription = useRef(null);
88
92
  // CONST
@@ -145,7 +149,7 @@ export default function GroupHeader(inProps) {
145
149
  const _backgroundCover = Object.assign({}, (scGroup.emotional_image
146
150
  ? { background: `url('${scGroup.emotional_image}') center / cover` }
147
151
  : { background: `url('${scPreferences.preferences[SCPreferences.IMAGES_USER_DEFAULT_COVER].value}') center / cover` }));
148
- return (_jsxs(Root, Object.assign({ id: id, className: classNames(classes.root, className) }, rest, { children: [_jsxs(Paper, Object.assign({ style: _backgroundCover, classes: { root: classes.cover } }, { children: [_jsx(Box, Object.assign({ className: classes.avatar }, { children: _jsx(Avatar, { children: _jsx("img", { alt: "group", src: scGroup.image_big ? scGroup.image_big : '' }) }) })), isGroupAdmin && (_jsxs(_Fragment, { children: [_jsx(ChangeGroupPicture, Object.assign({ groupId: scGroup.id, onChange: handleChangeAvatar, className: classes.changePicture }, ChangePictureProps)), _jsx("div", Object.assign({ className: classes.changeCover }, { children: _jsx(ChangeGroupCover, Object.assign({ groupId: scGroup.id, onChange: handleChangeCover }, ChangeCoverProps)) }))] }))] })), _jsxs(Box, Object.assign({ className: classes.info }, { children: [isGroupAdmin && _jsx(EditGroupButton, { group: scGroup, groupId: scGroup.id, onEditSuccess: (data) => setSCGroup(data) }), _jsx(Typography, Object.assign({ variant: "h5", className: classes.name }, { children: scGroup.name })), privateEnabled && (_jsxs(Box, Object.assign({ className: classes.visibility }, { children: [privateEnabled && (_jsx(_Fragment, { children: scGroup.privacy === SCGroupPrivacyType.PUBLIC ? (_jsxs(Typography, Object.assign({ className: classes.visibilityItem }, { children: [_jsx(Icon, { children: "public" }), _jsx(FormattedMessage, { id: "ui.groupHeader.visibility.public", defaultMessage: "ui.groupHeader.visibility.public" })] }))) : (_jsxs(Typography, Object.assign({ className: classes.visibilityItem }, { children: [_jsx(Icon, { children: "private" }), _jsx(FormattedMessage, { id: "ui.groupHeader.visibility.private", defaultMessage: "ui.groupHeader.visibility.private" })] }))) })), visibilityEnabled && (_jsxs(_Fragment, { children: [privateEnabled && _jsx(Bullet, {}), scGroup.visible ? (_jsxs(Typography, Object.assign({ className: classes.visibilityItem }, { children: [_jsx(Icon, { children: "visibility" }), _jsx(FormattedMessage, { id: "ui.groupHeader.visibility.visible", defaultMessage: "ui.groupHeader.visibility.visible" })] }))) : (_jsxs(Typography, Object.assign({ className: classes.visibilityItem }, { children: [_jsx(Icon, { children: "visibility_off" }), _jsx(FormattedMessage, { id: "ui.groupHeader.visibility.hidden", defaultMessage: "ui.groupHeader.visibility.hidden" })] })))] }))] }))), _jsx(_Fragment, { children: ((scGroup && scGroup.privacy === SCGroupPrivacyType.PUBLIC) ||
152
+ return (_jsxs(Root, Object.assign({ id: id, className: classNames(classes.root, className) }, rest, { children: [_jsxs(Paper, Object.assign({ style: _backgroundCover, classes: { root: classes.cover } }, { children: [_jsx(Box, Object.assign({ className: classes.avatar }, { children: _jsx(Avatar, { children: _jsx("img", { alt: "group", src: scGroup.image_big ? scGroup.image_big : '' }) }) })), isGroupAdmin && (_jsxs(_Fragment, { children: [_jsx(ChangeGroupPicture, Object.assign({ groupId: scGroup.id, onChange: handleChangeAvatar, className: classes.changePicture }, ChangePictureProps)), _jsx("div", Object.assign({ className: classes.changeCover }, { children: _jsx(ChangeGroupCover, Object.assign({ groupId: scGroup.id, onChange: handleChangeCover }, ChangeCoverProps)) }))] }))] })), _jsxs(Box, Object.assign({ className: classes.info }, { children: [isGroupAdmin && !isMobile && (_jsxs(Box, Object.assign({ className: classes.multiActions }, { children: [_jsx(EditGroupButton, { group: scGroup, groupId: scGroup.id, onEditSuccess: (data) => setSCGroup(data) }), _jsx(GroupActionsMenu, Object.assign({ group: scGroup, onEditSuccess: (data) => setSCGroup(data) }, GroupActionsProps))] }))), _jsx(Typography, Object.assign({ variant: "h5", className: classes.name }, { children: scGroup.name })), privateEnabled && (_jsxs(Box, Object.assign({ className: classes.visibility }, { children: [privateEnabled && (_jsx(_Fragment, { children: scGroup.privacy === SCGroupPrivacyType.PUBLIC ? (_jsxs(Typography, Object.assign({ className: classes.visibilityItem }, { children: [_jsx(Icon, { children: "public" }), _jsx(FormattedMessage, { id: "ui.groupHeader.visibility.public", defaultMessage: "ui.groupHeader.visibility.public" })] }))) : (_jsxs(Typography, Object.assign({ className: classes.visibilityItem }, { children: [_jsx(Icon, { children: "private" }), _jsx(FormattedMessage, { id: "ui.groupHeader.visibility.private", defaultMessage: "ui.groupHeader.visibility.private" })] }))) })), visibilityEnabled && (_jsxs(_Fragment, { children: [privateEnabled && _jsx(Bullet, {}), scGroup.visible ? (_jsxs(Typography, Object.assign({ className: classes.visibilityItem }, { children: [_jsx(Icon, { children: "visibility" }), _jsx(FormattedMessage, { id: "ui.groupHeader.visibility.visible", defaultMessage: "ui.groupHeader.visibility.visible" })] }))) : (_jsxs(Typography, Object.assign({ className: classes.visibilityItem }, { children: [_jsx(Icon, { children: "visibility_off" }), _jsx(FormattedMessage, { id: "ui.groupHeader.visibility.hidden", defaultMessage: "ui.groupHeader.visibility.hidden" })] })))] }))] }))), _jsx(_Fragment, { children: ((scGroup && scGroup.privacy === SCGroupPrivacyType.PUBLIC) ||
149
153
  scGroup.subscription_status === SCGroupSubscriptionStatusType.SUBSCRIBED ||
150
- isGroupAdmin) && (_jsxs(Box, Object.assign({ className: classes.members }, { children: [_jsx(Typography, Object.assign({ className: classes.membersCounter, component: "div" }, { children: _jsx(FormattedMessage, { id: "ui.groupHeader.members", defaultMessage: "ui.groupHeader.members", values: { total: scGroup.subscribers_counter } }) })), _jsx(GroupMembersButton, Object.assign({ groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, group: scGroup, autoHide: !isGroupAdmin }, GroupMembersButtonProps), scGroup.subscribers_counter)] }))) }), isGroupAdmin ? (_jsx(GroupInviteButton, { group: scGroup, groupId: scGroup.id })) : (_jsx(GroupSubscribeButton, Object.assign({ group: scGroup, onSubscribe: handleSubscribe }, GroupSubscribeButtonProps)))] }))] })));
154
+ isGroupAdmin) && (_jsxs(Box, Object.assign({ className: classes.members }, { children: [_jsx(Typography, Object.assign({ className: classes.membersCounter, component: "div" }, { children: _jsx(FormattedMessage, { id: "ui.groupHeader.members", defaultMessage: "ui.groupHeader.members", values: { total: scGroup.subscribers_counter } }) })), _jsx(GroupMembersButton, Object.assign({ groupId: scGroup === null || scGroup === void 0 ? void 0 : scGroup.id, group: scGroup, autoHide: !isGroupAdmin }, GroupMembersButtonProps), scGroup.subscribers_counter)] }))) }), isGroupAdmin ? (_jsxs(Box, { children: [_jsx(GroupInviteButton, { group: scGroup, groupId: scGroup.id }), isMobile && _jsx(GroupActionsMenu, Object.assign({ group: scGroup, onEditSuccess: (data) => setSCGroup(data) }, GroupActionsProps))] })) : (_jsx(GroupSubscribeButton, Object.assign({ group: scGroup, onSubscribe: handleSubscribe }, GroupSubscribeButtonProps)))] }))] })));
151
155
  }
@@ -1,6 +1,6 @@
1
1
  import { __rest } from "tslib";
2
2
  import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { useEffect, useMemo, useState } from 'react';
3
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
4
4
  import { styled } from '@mui/material/styles';
5
5
  import { Box, Button, Grid, TextField, Typography, useMediaQuery, useTheme } from '@mui/material';
6
6
  import { Endpoints, GroupService, http } from '@selfcommunity/api-services';
@@ -16,6 +16,8 @@ import { PREFIX } from './constants';
16
16
  import Group, { GroupSkeleton } from '../Group';
17
17
  import { DEFAULT_PAGINATION_OFFSET } from '../../constants/Pagination';
18
18
  import InfiniteScroll from '../../shared/InfiniteScroll';
19
+ import PubSub from 'pubsub-js';
20
+ import { SCGroupEventType, SCTopicType } from '../../constants/PubSub';
19
21
  const classes = {
20
22
  root: `${PREFIX}-root`,
21
23
  filters: `${PREFIX}-filter`,
@@ -83,6 +85,8 @@ export default function Groups(inProps) {
83
85
  scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY].value, [scPreferencesContext.preferences]);
84
86
  // CONST
85
87
  const authUserId = scUserContext.user ? scUserContext.user.id : null;
88
+ // REFS
89
+ const updatesSubscription = useRef(null);
86
90
  // HANDLERS
87
91
  const handleScrollUp = () => {
88
92
  window.scrollTo({ left: 0, top: 0, behavior: 'smooth' });
@@ -119,6 +123,28 @@ export default function Groups(inProps) {
119
123
  fetchGroups();
120
124
  }
121
125
  }, [contentAvailability, authUserId, search]);
126
+ /**
127
+ * Subscriber for pubsub callback
128
+ */
129
+ const onDeleteGroupHandler = useCallback((_msg, deleted) => {
130
+ setGroups((prev) => {
131
+ if (prev.some((e) => e.id === deleted)) {
132
+ return prev.filter((e) => e.id !== deleted);
133
+ }
134
+ return prev;
135
+ });
136
+ }, [groups]);
137
+ /**
138
+ * On mount, subscribe to receive event updates (only delete)
139
+ */
140
+ useEffect(() => {
141
+ if (groups) {
142
+ updatesSubscription.current = PubSub.subscribe(`${SCTopicType.GROUP}.${SCGroupEventType.DELETE}`, onDeleteGroupHandler);
143
+ }
144
+ return () => {
145
+ updatesSubscription.current && PubSub.unsubscribe(updatesSubscription.current);
146
+ };
147
+ }, [groups]);
122
148
  const handleNext = useMemo(() => () => {
123
149
  if (!next) {
124
150
  return;
@@ -0,0 +1,31 @@
1
+ import React from 'react';
2
+ import { DrawerProps } from '@mui/material';
3
+ export interface NavigationMenuDrawerProps extends DrawerProps {
4
+ /**
5
+ * Hide drawer header
6
+ * @default true
7
+ */
8
+ showDrawerHeader?: boolean;
9
+ /**
10
+ * Custom Drawer header content
11
+ * @default null
12
+ */
13
+ drawerHeaderContent?: React.ReactNode;
14
+ /**
15
+ * Custom Drawer content
16
+ * @default null
17
+ */
18
+ drawerContent?: React.ReactNode;
19
+ /**
20
+ * Props to spread to ScrollContainer component
21
+ * This lib use 'react-custom-scrollbars' component to perform scrollbars
22
+ * For more info: https://github.com/malte-wessel/react-custom-scrollbars/blob/master/docs/API.md
23
+ * @default {}
24
+ */
25
+ ScrollContainerProps?: Record<string, any>;
26
+ /**
27
+ * Any other properties
28
+ */
29
+ [p: string]: any;
30
+ }
31
+ export default function NavigationMenuDrawer(inProps: NavigationMenuDrawerProps): JSX.Element;
@@ -0,0 +1,32 @@
1
+ import { __rest } from "tslib";
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { styled } from '@mui/material/styles';
4
+ import { Box, Divider, Drawer, Icon, IconButton, List } from '@mui/material';
5
+ import classNames from 'classnames';
6
+ import { useThemeProps } from '@mui/system';
7
+ import ScrollContainer from '../../shared/ScrollContainer';
8
+ import DefaultDrawerContent from './DefaultDrawerContent';
9
+ import DefaultHeaderContent from './DefaultHeaderContent';
10
+ const PREFIX = 'SCNavigationMenuDrawer';
11
+ const classes = {
12
+ root: `${PREFIX}-root`,
13
+ logo: `${PREFIX}-logo`,
14
+ drawerRoot: `${PREFIX}-drawer-root`,
15
+ drawerHeader: `${PREFIX}-drawer-header`,
16
+ drawerHeaderAction: `${PREFIX}-drawer-header-action`,
17
+ drawerContent: `${PREFIX}-drawer-content`
18
+ };
19
+ const Root = styled(Drawer, {
20
+ name: PREFIX,
21
+ slot: 'Root',
22
+ overridesResolver: (props, styles) => styles.root
23
+ })(({ theme }) => ({}));
24
+ export default function NavigationMenuDrawer(inProps) {
25
+ // PROPS
26
+ const props = useThemeProps({
27
+ props: inProps,
28
+ name: PREFIX
29
+ });
30
+ const { className = null, showDrawerHeader = true, drawerHeaderContent = _jsx(DefaultHeaderContent, {}), drawerContent = _jsx(DefaultDrawerContent, {}), ScrollContainerProps = {}, open, onClose } = props, rest = __rest(props, ["className", "showDrawerHeader", "drawerHeaderContent", "drawerContent", "ScrollContainerProps", "open", "onClose"]);
31
+ return (_jsxs(Root, Object.assign({ anchor: "left", className: classNames(classes.root, className), open: open, onClose: onClose }, rest, { children: [showDrawerHeader && (_jsxs(_Fragment, { children: [_jsxs(Box, Object.assign({ className: classes.drawerHeader }, { children: [drawerHeaderContent, _jsx(IconButton, Object.assign({ className: classes.drawerHeaderAction, onClick: onClose }, { children: _jsx(Icon, { children: "close" }) }))] })), _jsx(Divider, {})] })), _jsx(ScrollContainer, Object.assign({}, ScrollContainerProps, { children: _jsx(List, Object.assign({ className: classes.drawerContent, onClick: onClose }, { children: drawerContent })) }))] })));
32
+ }