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

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 (30) hide show
  1. package/lib/cjs/components/ChangeGroupCover/ChangeGroupCover.js +24 -1
  2. package/lib/cjs/components/ChangeGroupPicture/ChangeGroupPicture.js +22 -4
  3. package/lib/cjs/components/Composer/Composer.js +3 -5
  4. package/lib/cjs/components/Composer/Content/ContentPost/ContentPost.js +4 -3
  5. package/lib/cjs/components/Composer/Layer/AudienceLayer/AudienceLayer.d.ts +1 -2
  6. package/lib/cjs/components/Composer/Layer/AudienceLayer/AudienceLayer.js +18 -6
  7. package/lib/cjs/components/EditGroupButton/EditGroupButton.js +4 -0
  8. package/lib/cjs/components/Group/Group.js +2 -2
  9. package/lib/cjs/components/GroupHeader/Skeleton.d.ts +2 -4
  10. package/lib/cjs/components/GroupHeader/Skeleton.js +10 -10
  11. package/lib/cjs/components/GroupInviteButton/GroupInviteButton.js +3 -3
  12. package/lib/cjs/components/GroupSubscribeButton/GroupSubscribeButton.js +3 -1
  13. package/lib/cjs/components/Groups/Groups.d.ts +13 -17
  14. package/lib/cjs/components/Groups/Groups.js +40 -93
  15. package/lib/esm/components/ChangeGroupCover/ChangeGroupCover.js +24 -1
  16. package/lib/esm/components/ChangeGroupPicture/ChangeGroupPicture.js +22 -4
  17. package/lib/esm/components/Composer/Composer.js +3 -5
  18. package/lib/esm/components/Composer/Content/ContentPost/ContentPost.js +4 -3
  19. package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.d.ts +1 -2
  20. package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.js +18 -6
  21. package/lib/esm/components/EditGroupButton/EditGroupButton.js +5 -1
  22. package/lib/esm/components/Group/Group.js +2 -2
  23. package/lib/esm/components/GroupHeader/Skeleton.d.ts +2 -4
  24. package/lib/esm/components/GroupHeader/Skeleton.js +10 -10
  25. package/lib/esm/components/GroupInviteButton/GroupInviteButton.js +3 -3
  26. package/lib/esm/components/GroupSubscribeButton/GroupSubscribeButton.js +4 -2
  27. package/lib/esm/components/Groups/Groups.d.ts +13 -17
  28. package/lib/esm/components/Groups/Groups.js +45 -98
  29. package/lib/umd/react-ui.js +1 -1
  30. package/package.json +4 -4
@@ -23,6 +23,10 @@ const messages = defineMessages({
23
23
  errorLoadImage: {
24
24
  id: 'ui.changeGroupCover.button.change.alertErrorImage',
25
25
  defaultMessage: 'ui.changeGroupCover.button.change.alertErrorImage'
26
+ },
27
+ errorImageSize: {
28
+ id: 'ui.changeGroupCover.alert',
29
+ defaultMessage: 'ui.changeGroupCover.alert'
26
30
  }
27
31
  });
28
32
  /**
@@ -73,7 +77,26 @@ export default function ChangeGroupCover(inProps) {
73
77
  */
74
78
  const handleUpload = (event) => {
75
79
  fileInput = event.target.files[0];
76
- isCreationMode ? onChange && onChange(fileInput) : handleSave();
80
+ if (fileInput) {
81
+ const reader = new FileReader();
82
+ reader.onload = (e) => {
83
+ const img = new Image();
84
+ img.onload = () => {
85
+ if (img.width < 1920) {
86
+ setAlert(intl.formatMessage(messages.errorImageSize));
87
+ }
88
+ else {
89
+ isCreationMode ? onChange && onChange(fileInput) : handleSave();
90
+ }
91
+ };
92
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
93
+ // @ts-ignore
94
+ img.src = e.target.result;
95
+ };
96
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
97
+ // @ts-ignore
98
+ reader.readAsDataURL(fileInput);
99
+ }
77
100
  };
78
101
  /**
79
102
  * Handles cover saving after upload action
@@ -14,8 +14,8 @@ import { defineMessages, useIntl } from 'react-intl';
14
14
  import { LoadingButton } from '@mui/lab';
15
15
  const messages = defineMessages({
16
16
  errorLoadImage: {
17
- id: 'ui.changeGroupCover.button.change.alertErrorImage',
18
- defaultMessage: 'ui.changeGroupCover.button.change.alertErrorImage'
17
+ id: 'ui.changeGroupPicture.alert',
18
+ defaultMessage: 'ui.changeGroupPicture.alert'
19
19
  }
20
20
  });
21
21
  const classes = {
@@ -74,9 +74,27 @@ export default function ChangeGroupPicture(inProps) {
74
74
  * @param event
75
75
  */
76
76
  function handleUpload(event) {
77
- fileInput = event.target.files[0];
78
- isCreationMode ? onChange && onChange(fileInput) : handleSave();
77
+ const fileInput = event.target.files[0];
78
+ if (fileInput) {
79
+ const reader = new FileReader();
80
+ reader.onload = (e) => {
81
+ const img = new Image();
82
+ img.onload = () => {
83
+ if (img.width < 600 && img.height < 600) {
84
+ setAlert(intl.formatMessage(messages.errorLoadImage));
85
+ }
86
+ else {
87
+ isCreationMode ? onChange && onChange(fileInput) : handleSave();
88
+ }
89
+ };
90
+ // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
91
+ // @ts-ignore
92
+ img.src = e.target.result;
93
+ };
94
+ reader.readAsDataURL(fileInput);
95
+ }
79
96
  }
97
+ // ui.changeGroupPicture.alert
80
98
  /**
81
99
  * Performs save avatar after upload
82
100
  */
@@ -27,7 +27,6 @@ import Attributes from './Attributes';
27
27
  import { PREFIX } from './constants';
28
28
  import ComposerSkeleton from './Skeleton';
29
29
  import CloseLayer from './Layer/CloseLayer';
30
- import { AudienceTypes } from './Layer/AudienceLayer/AudienceLayer';
31
30
  const DialogTransition = forwardRef(function Transition(props, ref) {
32
31
  return React.createElement(Fade, Object.assign({ ref: ref }, props));
33
32
  });
@@ -306,7 +305,7 @@ export default function Composer(inProps) {
306
305
  }
307
306
  }), [handleAddLayer, handleRemoveLayer, handleChangeCategories, categories]);
308
307
  const handleChangeAudience = useCallback((value) => {
309
- if (group) {
308
+ if (group || typeof value === 'object') {
310
309
  dispatch({ type: 'group', value });
311
310
  }
312
311
  else {
@@ -320,8 +319,7 @@ export default function Composer(inProps) {
320
319
  ComponentProps: {
321
320
  onClose: handleRemoveLayer,
322
321
  onSave: handleChangeAudience,
323
- defaultValue: group ? group : addressing,
324
- defaultType: group ? AudienceTypes.AUDIENCE_GROUP : addressing ? AudienceTypes.AUDIENCE_TAG : AudienceTypes.AUDIENCE_ALL
322
+ defaultValue: group || typeof addressing === 'object' ? group : addressing
325
323
  }
326
324
  }), [handleAddLayer, handleRemoveLayer, handleChangeAudience, addressing, group]);
327
325
  const handleChangeLocation = useCallback((value) => {
@@ -553,7 +551,7 @@ export default function Composer(inProps) {
553
551
  }),
554
552
  React.createElement(IconButton, { disabled: isSubmitting, onClick: handleAddCategoryLayer },
555
553
  React.createElement(Icon, null, "category")),
556
- React.createElement(IconButton, { disabled: isSubmitting || !features.includes(SCFeatureName.TAGGING), onClick: handleAddAudienceLayer }, addressing === null || addressing.length === 0 ? React.createElement(Icon, null, "public") : React.createElement(Icon, null, "label")),
554
+ React.createElement(IconButton, { disabled: isSubmitting || !features.includes(SCFeatureName.TAGGING), onClick: handleAddAudienceLayer }, addressing === null || addressing.length === 0 ? (React.createElement(Icon, null, "public")) : typeof addressing === 'object' ? (React.createElement(Icon, null, "groups")) : (React.createElement(Icon, null, "label"))),
557
555
  preferences[SCPreferences.ADDONS_POST_GEOLOCATION_ENABLED].value && (React.createElement(IconButton, { disabled: isSubmitting, onClick: handleAddLocationLayer, color: location !== null ? 'primary' : 'default' },
558
556
  React.createElement(Icon, null, "add_location_alt"))))),
559
557
  layer && (React.createElement(LayerTransitionRoot, { className: classes.layerTransitionRoot, in: true, container: dialogRef.current, direction: "left" },
@@ -22,7 +22,8 @@ const DEFAULT_POST = {
22
22
  categories: [],
23
23
  medias: [],
24
24
  html: '',
25
- addressing: []
25
+ addressing: [],
26
+ group: null
26
27
  };
27
28
  export default (props) => {
28
29
  // PROPS
@@ -40,7 +41,7 @@ export default (props) => {
40
41
  }, [value]);
41
42
  // RENDER
42
43
  return (React.createElement(Root, { className: classNames(classes.root, className) },
43
- generalError && React.createElement(Typography, { className: classes.generalError },
44
- React.createElement(FormattedMessage, { id: `ui.composer.error.${generalError}`, defaultMessage: `ui.composer.error.${generalError}` })),
44
+ generalError && (React.createElement(Typography, { className: classes.generalError },
45
+ React.createElement(FormattedMessage, { id: `ui.composer.error.${generalError}`, defaultMessage: `ui.composer.error.${generalError}` }))),
45
46
  React.createElement(Editor, Object.assign({ ref: editorRef }, EditorProps, { editable: !disabled, className: classes.editor, onChange: handleChangeHtml, defaultValue: value.html }))));
46
47
  };
@@ -10,9 +10,8 @@ export declare enum AudienceTypes {
10
10
  AUDIENCE_GROUP = "group"
11
11
  }
12
12
  export interface AudienceLayerProps extends Omit<BoxProps, 'defaultValue'>, ComposerLayerProps {
13
- defaultType: AudienceTypes;
14
13
  defaultValue: SCTagType[] | SCGroupType;
15
14
  TextFieldProps?: TextFieldProps;
16
15
  }
17
- declare const AudienceLayer: React.ForwardRefExoticComponent<Pick<AudienceLayerProps, "p" | "slot" | "style" | "title" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "border" | "borderTop" | "borderRight" | "borderBottom" | "borderLeft" | "borderColor" | "borderRadius" | "display" | "displayPrint" | "overflow" | "textOverflow" | "visibility" | "whiteSpace" | "flexBasis" | "flexDirection" | "flexWrap" | "justifyContent" | "alignItems" | "alignContent" | "order" | "flex" | "flexGrow" | "flexShrink" | "alignSelf" | "justifyItems" | "justifySelf" | "gap" | "columnGap" | "rowGap" | "gridColumn" | "gridRow" | "gridAutoFlow" | "gridAutoColumns" | "gridAutoRows" | "gridTemplateColumns" | "gridTemplateRows" | "gridTemplateAreas" | "gridArea" | "bgcolor" | "zIndex" | "position" | "top" | "right" | "bottom" | "left" | "boxShadow" | "width" | "maxWidth" | "minWidth" | "height" | "maxHeight" | "minHeight" | "boxSizing" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "my" | "pt" | "pr" | "pb" | "pl" | "px" | "py" | "margin" | "marginTop" | "marginRight" | "marginBottom" | "marginLeft" | "marginX" | "marginY" | "marginInline" | "marginInlineStart" | "marginInlineEnd" | "marginBlock" | "marginBlockStart" | "marginBlockEnd" | "padding" | "paddingTop" | "paddingRight" | "paddingBottom" | "paddingLeft" | "paddingX" | "paddingY" | "paddingInline" | "paddingInlineStart" | "paddingInlineEnd" | "paddingBlock" | "paddingBlockStart" | "paddingBlockEnd" | "typography" | "fontFamily" | "fontSize" | "fontStyle" | "fontWeight" | "letterSpacing" | "lineHeight" | "textAlign" | "textTransform" | "component" | "sx" | "classes" | "onClose" | "TextFieldProps" | "defaultType" | "onSave"> & React.RefAttributes<unknown>>;
16
+ declare const AudienceLayer: React.ForwardRefExoticComponent<Pick<AudienceLayerProps, "p" | "slot" | "style" | "title" | "key" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "placeholder" | "spellCheck" | "tabIndex" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "children" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "border" | "borderTop" | "borderRight" | "borderBottom" | "borderLeft" | "borderColor" | "borderRadius" | "display" | "displayPrint" | "overflow" | "textOverflow" | "visibility" | "whiteSpace" | "flexBasis" | "flexDirection" | "flexWrap" | "justifyContent" | "alignItems" | "alignContent" | "order" | "flex" | "flexGrow" | "flexShrink" | "alignSelf" | "justifyItems" | "justifySelf" | "gap" | "columnGap" | "rowGap" | "gridColumn" | "gridRow" | "gridAutoFlow" | "gridAutoColumns" | "gridAutoRows" | "gridTemplateColumns" | "gridTemplateRows" | "gridTemplateAreas" | "gridArea" | "bgcolor" | "zIndex" | "position" | "top" | "right" | "bottom" | "left" | "boxShadow" | "width" | "maxWidth" | "minWidth" | "height" | "maxHeight" | "minHeight" | "boxSizing" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "my" | "pt" | "pr" | "pb" | "pl" | "px" | "py" | "margin" | "marginTop" | "marginRight" | "marginBottom" | "marginLeft" | "marginX" | "marginY" | "marginInline" | "marginInlineStart" | "marginInlineEnd" | "marginBlock" | "marginBlockStart" | "marginBlockEnd" | "padding" | "paddingTop" | "paddingRight" | "paddingBottom" | "paddingLeft" | "paddingX" | "paddingY" | "paddingInline" | "paddingInlineStart" | "paddingInlineEnd" | "paddingBlock" | "paddingBlockStart" | "paddingBlockEnd" | "typography" | "fontFamily" | "fontSize" | "fontStyle" | "fontWeight" | "letterSpacing" | "lineHeight" | "textAlign" | "textTransform" | "component" | "sx" | "classes" | "onClose" | "TextFieldProps" | "onSave"> & React.RefAttributes<unknown>>;
18
17
  export default AudienceLayer;
@@ -32,10 +32,10 @@ const Root = styled(Box, {
32
32
  })(() => ({}));
33
33
  const AudienceLayer = React.forwardRef((props, ref) => {
34
34
  // Props
35
- const { className, onClose, onSave, defaultType = AudienceTypes.AUDIENCE_TAG, defaultValue = AudienceTypes.AUDIENCE_TAG ? [] : null, TextFieldProps = {
35
+ const { className, onClose, onSave, defaultValue = AudienceTypes.AUDIENCE_TAG ? [] : null, TextFieldProps = {
36
36
  variant: 'outlined',
37
37
  label: React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.tags.label", defaultMessage: "ui.composer.layer.audience.tags.label" })
38
- } } = props, rest = __rest(props, ["className", "onClose", "onSave", "defaultType", "defaultValue", "TextFieldProps"]);
38
+ } } = props, rest = __rest(props, ["className", "onClose", "onSave", "defaultValue", "TextFieldProps"]);
39
39
  // STATE
40
40
  const [autocompleteOpen, setAutocompleteOpen] = useState(false);
41
41
  const [audience, setAudience] = useState(
@@ -43,7 +43,7 @@ const AudienceLayer = React.forwardRef((props, ref) => {
43
43
  // @ts-ignore
44
44
  defaultValue === null || defaultValue.length === 0
45
45
  ? AudienceTypes.AUDIENCE_ALL
46
- : defaultType === AudienceTypes.AUDIENCE_GROUP
46
+ : typeof defaultValue === 'object'
47
47
  ? AudienceTypes.AUDIENCE_GROUP
48
48
  : AudienceTypes.AUDIENCE_TAG);
49
49
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
@@ -55,7 +55,7 @@ const AudienceLayer = React.forwardRef((props, ref) => {
55
55
  const handleSave = useCallback(
56
56
  // eslint-disable-next-line @typescript-eslint/ban-ts-comment
57
57
  // @ts-ignore
58
- () => (defaultType === AudienceTypes.AUDIENCE_GROUP ? onSave(value) : onSave((value === null || value === void 0 ? void 0 : value.length) && (value === null || value === void 0 ? void 0 : value.length) > 0 ? value : null)), [value, onSave]);
58
+ () => (typeof defaultValue === 'object' ? onSave(value) : onSave((value === null || value === void 0 ? void 0 : value.length) && (value === null || value === void 0 ? void 0 : value.length) > 0 ? value : null)), [value, onSave]);
59
59
  const handleChange = useCallback((event, tags) => setValue(tags), []);
60
60
  const handleGroupChange = useCallback((group) => setValue(group), []);
61
61
  const handleChangeAudience = useCallback((event, data) => setAudience(data), []);
@@ -72,8 +72,20 @@ const AudienceLayer = React.forwardRef((props, ref) => {
72
72
  React.createElement(DialogContent, { className: classes.content },
73
73
  React.createElement(Tabs, { value: audience, onChange: handleChangeAudience, "aria-label": "audience type" },
74
74
  React.createElement(Tab, { value: AudienceTypes.AUDIENCE_ALL, icon: React.createElement(Icon, null, "public"), label: React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.all", defaultMessage: "ui.composer.layer.audience.all" }) }),
75
- React.createElement(Tab, { disabled: defaultType === AudienceTypes.AUDIENCE_TAG, value: AudienceTypes.AUDIENCE_GROUP, icon: React.createElement(Icon, null, "groups"), label: React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.group", defaultMessage: "ui.composer.layer.audience.group" }) }),
76
- React.createElement(Tab, { disabled: defaultType === AudienceTypes.AUDIENCE_GROUP, value: AudienceTypes.AUDIENCE_TAG, icon: React.createElement(Icon, null, "label"), label: React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.tag", defaultMessage: "ui.composer.layer.audience.tag" }) })),
75
+ React.createElement(Tab
76
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
77
+ // @ts-ignore
78
+ , {
79
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
80
+ // @ts-ignore
81
+ disabled: defaultValue && defaultValue.length !== 0, value: AudienceTypes.AUDIENCE_GROUP, icon: React.createElement(Icon, null, "groups"), label: React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.group", defaultMessage: "ui.composer.layer.audience.group" }) }),
82
+ React.createElement(Tab
83
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
84
+ // @ts-ignore
85
+ , {
86
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
87
+ // @ts-ignore
88
+ disabled: typeof defaultValue === 'object', value: AudienceTypes.AUDIENCE_TAG, icon: React.createElement(Icon, null, "label"), label: React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.tag", defaultMessage: "ui.composer.layer.audience.tag" }) })),
77
89
  React.createElement(Typography, { className: classes.message },
78
90
  audience === AudienceTypes.AUDIENCE_ALL && (React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.all.message", defaultMessage: "ui.composer.audience.layer.all.message" })),
79
91
  audience === AudienceTypes.AUDIENCE_GROUP && (React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.group.message", defaultMessage: "ui.composer.audience.layer.group.message" })),
@@ -3,7 +3,7 @@ import React from 'react';
3
3
  import { useThemeProps } from '@mui/system';
4
4
  import { styled } from '@mui/material/styles';
5
5
  import { FormattedMessage } from 'react-intl';
6
- import { useSCFetchGroup } from '@selfcommunity/react-core';
6
+ import { useSCFetchGroup, useSCUser } from '@selfcommunity/react-core';
7
7
  import classNames from 'classnames';
8
8
  import CreateGroupButton from '../CreateGroupButton';
9
9
  const PREFIX = 'SCEditGroupButton';
@@ -42,10 +42,14 @@ export default function EditGroupButton(inProps) {
42
42
  });
43
43
  const { className, groupId, group, onEditSuccess } = props, rest = __rest(props, ["className", "groupId", "group", "onEditSuccess"]);
44
44
  const { scGroup, setSCGroup } = useSCFetchGroup({ id: groupId, group });
45
+ const scUserContext = useSCUser();
45
46
  const handleSuccess = (data) => {
46
47
  setSCGroup(data);
47
48
  onEditSuccess && onEditSuccess(data);
48
49
  };
50
+ if (!scUserContext.user) {
51
+ return null;
52
+ }
49
53
  /**
50
54
  * Renders root object
51
55
  */
@@ -61,7 +61,7 @@ export default function Group(inProps) {
61
61
  props: inProps,
62
62
  name: PREFIX
63
63
  });
64
- const { groupId = null, group = null, className = null, elevation, hideActions = false, groupSubscribeButtonProps = {}, buttonProps = {}, visible = true } = props, rest = __rest(props, ["groupId", "group", "className", "elevation", "hideActions", "groupSubscribeButtonProps", "buttonProps", "visible"]);
64
+ const { groupId = null, group = null, className = null, elevation, hideActions = false, groupSubscribeButtonProps = {}, visible = true } = props, rest = __rest(props, ["groupId", "group", "className", "elevation", "hideActions", "groupSubscribeButtonProps", "visible"]);
65
65
  // STATE
66
66
  const { scGroup } = useSCFetchGroup({ id: groupId, group });
67
67
  // CONTEXT
@@ -88,6 +88,6 @@ export default function Group(inProps) {
88
88
  * Renders root object
89
89
  */
90
90
  return (React.createElement(React.Fragment, null,
91
- React.createElement(Root, Object.assign({ elevation: elevation }, rest, { className: classNames(classes.root, className), ButtonBaseProps: buttonProps !== null && buttonProps !== void 0 ? buttonProps : { component: Link, to: scRoutingContext.url(SCRoutes.GROUP_ROUTE_NAME, scGroup) }, image: React.createElement(Avatar, { alt: scGroup.name, src: scGroup.image_medium, className: classes.avatar }), primary: scGroup.name, secondary: `${intl.formatMessage(messages.groupMembers, { total: scGroup.subscribers_counter })}`, actions: hideActions ? null : renderAuthenticatedActions() })),
91
+ React.createElement(Root, Object.assign({ elevation: elevation }, rest, { className: classNames(classes.root, className), ButtonBaseProps: { component: Link, to: scRoutingContext.url(SCRoutes.GROUP_ROUTE_NAME, scGroup) }, image: React.createElement(Avatar, { alt: scGroup.name, src: scGroup.image_medium, className: classes.avatar }), primary: scGroup.name, secondary: `${intl.formatMessage(messages.groupMembers, { total: scGroup.subscribers_counter })}`, actions: hideActions ? null : renderAuthenticatedActions() })),
92
92
  openAlert && React.createElement(UserDeletedSnackBar, { open: openAlert, handleClose: () => setOpenAlert(false) })));
93
93
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * > API documentation for the Community-JS Group Headerr Skeleton component. Learn about the available props and the CSS API.
2
+ * > API documentation for the Community-JS Group Header Skeleton component. Learn about the available props and the CSS API.
3
3
 
4
4
  #### Import
5
5
 
@@ -18,9 +18,7 @@
18
18
  |root|.SCGroupHeader-skeleton-root|Styles applied to the root element.|
19
19
  |avatar|.SCGroupHeader-avatar|Styles applied to the avatar element.|
20
20
  |cover|.SCGroupHeader-cover|Styles applied to the cover element.|
21
- |actions|.SCGroupHeader-actions|Styles applied to the actions section.|
22
- |section|.SCGroupHeader-section|Styles applied to the info section.|
23
- |username|.SCGroupHeader-username|Styles applied to the username element.|
21
+ |info|.SCGroupHeader-info|Styles applied to the info info.|
24
22
  *
25
23
  */
26
24
  declare function GroupHeaderSkeleton(): JSX.Element;
@@ -7,16 +7,14 @@ const classes = {
7
7
  root: `${PREFIX}-skeleton-root`,
8
8
  cover: `${PREFIX}-cover`,
9
9
  avatar: `${PREFIX}-avatar`,
10
- actions: `${PREFIX}-actions`,
11
- section: `${PREFIX}-section`,
12
- username: `${PREFIX}-username`
10
+ info: `${PREFIX}-info`
13
11
  };
14
12
  const Root = styled(Box, {
15
13
  name: PREFIX,
16
14
  slot: 'SkeletonRoot'
17
15
  })(() => ({}));
18
16
  /**
19
- * > API documentation for the Community-JS Group Headerr Skeleton component. Learn about the available props and the CSS API.
17
+ * > API documentation for the Community-JS Group Header Skeleton component. Learn about the available props and the CSS API.
20
18
 
21
19
  #### Import
22
20
 
@@ -35,9 +33,7 @@ const Root = styled(Box, {
35
33
  |root|.SCGroupHeader-skeleton-root|Styles applied to the root element.|
36
34
  |avatar|.SCGroupHeader-avatar|Styles applied to the avatar element.|
37
35
  |cover|.SCGroupHeader-cover|Styles applied to the cover element.|
38
- |actions|.SCGroupHeader-actions|Styles applied to the actions section.|
39
- |section|.SCGroupHeader-section|Styles applied to the info section.|
40
- |username|.SCGroupHeader-username|Styles applied to the username element.|
36
+ |info|.SCGroupHeader-info|Styles applied to the info info.|
41
37
  *
42
38
  */
43
39
  function GroupHeaderSkeleton() {
@@ -46,8 +42,12 @@ function GroupHeaderSkeleton() {
46
42
  React.createElement(Skeleton, { className: classes.cover, animation: "wave", variant: "rectangular" }),
47
43
  React.createElement(Box, { className: classes.avatar },
48
44
  React.createElement(Skeleton, { animation: "wave", variant: "circular", width: theme.selfcommunity.group.avatar.sizeLarge, height: theme.selfcommunity.group.avatar.sizeLarge })),
49
- React.createElement(Box, { className: classes.section },
50
- React.createElement(Typography, { variant: "h5", className: classes.username },
51
- React.createElement(Skeleton, { animation: "wave", sx: { height: 30, width: 100 } })))));
45
+ React.createElement(Box, { className: classes.info },
46
+ React.createElement(Typography, { variant: "h5" },
47
+ React.createElement(Skeleton, { animation: "wave", sx: { height: 30, width: 200 } })),
48
+ React.createElement(Typography, null,
49
+ React.createElement(Skeleton, { animation: "wave", sx: { height: 20, width: 150 } })),
50
+ React.createElement(Typography, null,
51
+ React.createElement(Skeleton, { animation: "wave", sx: { height: 20, width: 100 } })))));
52
52
  }
53
53
  export default GroupHeaderSkeleton;
@@ -224,9 +224,9 @@ export default function GroupInviteButton(inProps) {
224
224
  setList((prev) => [...prev, option]);
225
225
  };
226
226
  /**
227
- * If there's no authUserId, component is hidden.
227
+ * If in group edit mode and logged-in user is not also the group manager, the component is hidden.
228
228
  // */
229
- if (!canEdit) {
229
+ if (group && !canEdit) {
230
230
  return null;
231
231
  }
232
232
  /**
@@ -240,7 +240,7 @@ export default function GroupInviteButton(inProps) {
240
240
  React.createElement(Icon, { fontSize: "medium" }, "arrow_back")),
241
241
  React.createElement(Typography, { className: classes.dialogTitle },
242
242
  React.createElement(FormattedMessage, { id: "ui.groupInviteButton.dialog.title", defaultMessage: "ui.groupInviteButton.dialog.title" })),
243
- React.createElement(LoadingButton, { size: "small", color: "secondary", variant: "contained", onClick: handleSendInvitations, loading: isSending },
243
+ React.createElement(LoadingButton, { size: "small", color: "secondary", variant: "contained", onClick: handleSendInvitations, loading: isSending, disabled: !invited.length },
244
244
  React.createElement(FormattedMessage, { id: "ui.groupInviteButton.dialog.button.end", defaultMessage: "ui.groupInviteButton.dialog.button.end" }))) },
245
245
  React.createElement(Box, { className: classes.dialogContent },
246
246
  React.createElement(Autocomplete, { className: classes.autocomplete, loading: loading, size: "small", multiple: true, freeSolo: true, disableClearable: true, options: suggested, onChange: handleChange, onInputChange: handleInputChange, inputValue: value, value: invited, getOptionLabel: (option) => (option ? option.username : '...'), isOptionEqualToValue: (option, value) => (option ? value.id === option.id : false), renderTags: () => null, renderOption: (props, option) => (React.createElement(Box, Object.assign({ component: "li" }, props),
@@ -1,5 +1,5 @@
1
1
  import { __rest } from "tslib";
2
- import React, { useEffect, useState } from 'react';
2
+ import React, { useEffect, useMemo, useState } from 'react';
3
3
  import { styled } from '@mui/material/styles';
4
4
  import { CacheStrategies, Logger } from '@selfcommunity/utils';
5
5
  import { useSCContext, useSCFetchGroup, useSCUser } from '@selfcommunity/react-core';
@@ -41,6 +41,7 @@ const Root = styled(LoadingButton, {
41
41
  * @param inProps
42
42
  */
43
43
  export default function GroupSubscribeButton(inProps) {
44
+ var _a;
44
45
  // PROPS
45
46
  const props = useThemeProps({
46
47
  props: inProps,
@@ -60,6 +61,7 @@ export default function GroupSubscribeButton(inProps) {
60
61
  group,
61
62
  cacheStrategy: authUserId ? CacheStrategies.CACHE_FIRST : CacheStrategies.STALE_WHILE_REVALIDATE
62
63
  });
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]);
63
65
  useEffect(() => {
64
66
  /**
65
67
  * Call scGroupsManager.subscriptionStatus inside an effect
@@ -117,7 +119,7 @@ export default function GroupSubscribeButton(inProps) {
117
119
  }
118
120
  return _status;
119
121
  };
120
- if (!scGroup || (scGroup && !scGroup.subscription_status)) {
122
+ if (!scGroup || (scGroup && !scGroup.subscription_status) || canEdit) {
121
123
  return null;
122
124
  }
123
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()));
@@ -1,31 +1,27 @@
1
+ import { SCGroupType } from '@selfcommunity/types';
1
2
  import { EndpointType } from '@selfcommunity/api-services';
2
- import { CacheStrategies } from '@selfcommunity/utils';
3
3
  import { GroupProps } from '../Group';
4
4
  export interface GroupsProps {
5
5
  /**
6
- * Endpoint to call
7
- */
8
- endpoint: EndpointType;
9
- /**
10
- * Hides this component
11
- * @default false
6
+ * Overrides or extends the styles applied to the component.
7
+ * @default null
12
8
  */
13
- autoHide?: boolean;
9
+ className?: string;
14
10
  /**
15
- * Limit the number of users to show
16
- * @default false
11
+ * Endpoint to call
17
12
  */
18
- limit?: number;
13
+ endpoint: EndpointType;
19
14
  /**
20
- * Caching strategies
21
- * @default CacheStrategies.CACHE_FIRST
15
+ * Props to spread to single group object
16
+ * @default {variant: 'outlined', ButtonBaseProps: {disableRipple: 'true'}}
22
17
  */
23
- cacheStrategy?: CacheStrategies;
18
+ GroupComponentProps?: GroupProps;
24
19
  /**
25
- * Props to spread to single group object
26
- * @default empty object
20
+ * Prefetch groups. Useful for SSR.
21
+ * Use this to init the component with groups
22
+ * @default null
27
23
  */
28
- GroupProps?: GroupProps;
24
+ prefetchedGroups?: SCGroupType[];
29
25
  /**
30
26
  * Other props
31
27
  */
@@ -1,11 +1,10 @@
1
- import { __rest } from "tslib";
2
- import React, { useEffect, useMemo, useReducer } from 'react';
1
+ import { __awaiter, __rest } from "tslib";
2
+ import React, { useEffect, useMemo, useState } from 'react';
3
3
  import { styled } from '@mui/material/styles';
4
- import { Box, Button, Grid, Typography } from '@mui/material';
4
+ import { Box, Grid, Typography } from '@mui/material';
5
5
  import { http } from '@selfcommunity/api-services';
6
- import { CacheStrategies, Logger } from '@selfcommunity/utils';
7
- import { SCCache, SCPreferences, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
8
- import { actionWidgetTypes, dataWidgetReducer, stateWidgetInitializer } from '../../utils/widget';
6
+ import { Logger } from '@selfcommunity/utils';
7
+ import { SCPreferences, useIsComponentMountedRef, useSCPreferences, useSCUser } from '@selfcommunity/react-core';
9
8
  import Skeleton from './Skeleton';
10
9
  import { FormattedMessage } from 'react-intl';
11
10
  import classNames from 'classnames';
@@ -63,116 +62,64 @@ export default function Groups(inProps) {
63
62
  props: inProps,
64
63
  name: PREFIX
65
64
  });
66
- const { endpoint, autoHide = false, limit = 6, className, cacheStrategy = CacheStrategies.NETWORK_ONLY, onHeightChange, onStateChange, GroupProps = { variant: 'outlined', ButtonBaseProps: { disableRipple: true, component: Box } } } = props, rest = __rest(props, ["endpoint", "autoHide", "limit", "className", "cacheStrategy", "onHeightChange", "onStateChange", "GroupProps"]);
65
+ const { endpoint, className, GroupComponentProps = { variant: 'outlined', ButtonBaseProps: { disableRipple: true, component: Box } }, prefetchedGroups = [] } = props, rest = __rest(props, ["endpoint", "className", "GroupComponentProps", "prefetchedGroups"]);
67
66
  // STATE
68
- const [state, dispatch] = useReducer(dataWidgetReducer, {
69
- isLoadingNext: false,
70
- next: null,
71
- cacheKey: SCCache.getWidgetStateCacheKey(SCCache.GROUPS_LIST_TOOLS_STATE_CACHE_PREFIX_KEY),
72
- cacheStrategy,
73
- visibleItems: limit
74
- }, stateWidgetInitializer);
67
+ const [groups, setGroups] = useState([]);
68
+ const [loading, setLoading] = useState(true);
75
69
  // CONTEXT
76
70
  const scUserContext = useSCUser();
77
71
  const scPreferencesContext = useSCPreferences();
78
72
  // MEMO
79
73
  const contentAvailability = useMemo(() => SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY in scPreferencesContext.preferences &&
80
74
  scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_CONTENT_AVAILABILITY].value, [scPreferencesContext.preferences]);
81
- // HOOKS
82
- // const theme = useTheme<SCThemeType>();
83
- // const isMobile = useMediaQuery(theme.breakpoints.down('md'));
75
+ // CONST
76
+ const authUserId = scUserContext.user ? scUserContext.user.id : null;
77
+ // REFS
78
+ const isMountedRef = useIsComponentMountedRef();
84
79
  /**
85
- * Initialize component
86
- * Fetch data only if the component is not initialized, and it is not loading data
80
+ * Fetches groups list
87
81
  */
88
- const _initComponent = useMemo(() => () => {
89
- if (!state.initialized && !state.isLoadingNext) {
90
- dispatch({ type: actionWidgetTypes.LOADING_NEXT });
91
- http
92
- .request({
93
- url: endpoint.url({ limit }),
94
- method: endpoint.method
95
- })
96
- .then((payload) => {
97
- dispatch({ type: actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: Object.assign(Object.assign({}, payload.data), { initialized: true }) });
98
- })
99
- .catch((error) => {
100
- dispatch({ type: actionWidgetTypes.LOAD_NEXT_FAILURE, payload: { errorLoadNext: error } });
101
- Logger.error(SCOPE_SC_UI, error);
102
- });
103
- }
104
- }, [state.isLoadingNext, state.initialized, endpoint, limit, dispatch]);
105
- // EFFECTS
106
- useEffect(() => {
107
- var _a;
108
- let _t;
109
- if ((contentAvailability || (!contentAvailability && ((_a = scUserContext.user) === null || _a === void 0 ? void 0 : _a.id))) && scUserContext.user !== undefined) {
110
- _t = setTimeout(_initComponent);
111
- return () => {
112
- _t && clearTimeout(_t);
113
- };
114
- }
115
- }, [scUserContext.user, contentAvailability]);
116
- useEffect(() => {
117
- if (state.next && state.results.length === limit && state.initialized) {
118
- dispatch({ type: actionWidgetTypes.LOADING_NEXT });
119
- http
120
- .request({
121
- url: endpoint.url({ offset: limit, limit: 10 }),
122
- method: endpoint.method
123
- })
124
- .then((payload) => {
125
- dispatch({ type: actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: payload.data });
126
- })
127
- .catch((error) => {
128
- dispatch({ type: actionWidgetTypes.LOAD_NEXT_FAILURE, payload: { errorLoadNext: error } });
129
- Logger.error(SCOPE_SC_UI, error);
130
- });
131
- }
132
- }, [state.next, state.results.length, state.initialized, limit]);
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
86
+ });
87
+ const data = response.data;
88
+ return data.next ? data.results.concat(yield fetchGroups(data.next)) : data.results;
89
+ });
133
90
  /**
134
- * Virtual feed update
91
+ * On mount, fetches groups list
135
92
  */
136
93
  useEffect(() => {
137
- onHeightChange && onHeightChange();
138
- }, [state.results]);
139
- useEffect(() => {
140
- if (!endpoint || (!contentAvailability && !scUserContext.user)) {
94
+ if (!contentAvailability && !authUserId) {
141
95
  return;
142
96
  }
143
- else if (cacheStrategy === CacheStrategies.NETWORK_ONLY) {
144
- onStateChange && onStateChange({ cacheStrategy: CacheStrategies.CACHE_FIRST });
97
+ else if (prefetchedGroups.length) {
98
+ setGroups(prefetchedGroups);
99
+ setLoading(false);
145
100
  }
146
- }, [scUserContext.user, endpoint, contentAvailability]);
147
- useEffect(() => {
148
- if (!endpoint || !scUserContext.user || !state.initialized) {
149
- return;
101
+ 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
+ });
150
112
  }
151
- }, []);
152
- // HANDLERS
153
- const handleNext = useMemo(() => () => {
154
- dispatch({ type: actionWidgetTypes.LOADING_NEXT });
155
- http
156
- .request({
157
- url: state.next,
158
- method: endpoint.method
159
- })
160
- .then((res) => {
161
- dispatch({ type: actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: res.data });
162
- });
163
- }, [dispatch, state.next, state.isLoadingNext, state.initialized, endpoint.method]);
113
+ }, [contentAvailability, authUserId, prefetchedGroups.length]);
164
114
  // RENDER
165
- if ((autoHide && !state.count && state.initialized) || (!contentAvailability && !scUserContext.user) || !endpoint) {
115
+ if (!contentAvailability && !scUserContext.user) {
166
116
  return React.createElement(HiddenPlaceholder, null);
167
117
  }
168
- if (!state.initialized) {
169
- return React.createElement(Skeleton, null);
170
- }
171
- const content = (React.createElement(React.Fragment, null, !state.count ? (React.createElement(Typography, { className: classes.noResults, variant: "body2" },
172
- React.createElement(FormattedMessage, { id: "ui.groupRequestsWidget.subtitle.noResults", defaultMessage: "" }))) : (React.createElement(React.Fragment, null,
173
- React.createElement(Grid, { container: true, spacing: { xs: 3 }, className: classes.groups }, state.results.slice(0, state.visibleItems).map((group) => (React.createElement(Grid, { item: true, xs: 12, sm: 8, md: 6, key: group.id, className: classes.item },
174
- React.createElement(Group, Object.assign({ group: group, groupId: group.id }, GroupProps)))))),
175
- state.count > state.visibleItems && (React.createElement(Button, { className: classes.showMore, onClick: handleNext },
176
- React.createElement(FormattedMessage, { id: "ui.groupRequestsWidget.button.showMore", defaultMessage: "ui.groupRequestsWidget.button.showMore" })))))));
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)))))))))));
177
124
  return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, rest), content));
178
125
  }