@selfcommunity/react-ui 0.7.0-alpha.357 → 0.7.0-alpha.359

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.
@@ -16,7 +16,7 @@ export interface AttributesProps extends Omit<BoxProps, 'value' | 'onChange' | '
16
16
  * @param value
17
17
  * @default empty object
18
18
  */
19
- onClick?: (attribute: 'categories' | 'addressing') => void;
19
+ onClick?: (attribute: 'categories' | 'addressing' | 'location') => void;
20
20
  }
21
21
  declare const _default: (props: AttributesProps) => JSX.Element;
22
22
  export default _default;
@@ -32,10 +32,16 @@ exports.default = (props) => {
32
32
  const handleClickTag = (0, react_1.useCallback)(() => {
33
33
  onClick && onClick('addressing');
34
34
  }, [onClick]);
35
+ const handleDeleteLocation = (0, react_1.useCallback)(() => {
36
+ onChange && onChange(Object.assign(Object.assign({}, value), { location: null }));
37
+ }, [value, onChange]);
38
+ const handleClickLocation = (0, react_1.useCallback)(() => {
39
+ onClick && onClick('location');
40
+ }, [onClick]);
35
41
  return (react_1.default.createElement(Root, { className: (0, classnames_1.default)(classes.root, className) },
36
42
  ((_a = value === null || value === void 0 ? void 0 : value.categories) === null || _a === void 0 ? void 0 : _a.length) > 0 &&
37
43
  (value === null || value === void 0 ? void 0 : value.categories.map((c) => (react_1.default.createElement(material_1.Chip, { key: c.id, label: c.name, onDelete: handleDeleteCategory(c.id), icon: react_1.default.createElement(Icon_1.default, null, "category"), onClick: handleClickCategory })))),
38
44
  ((_b = value === null || value === void 0 ? void 0 : value.addressing) === null || _b === void 0 ? void 0 : _b.length) > 0 &&
39
45
  (value === null || value === void 0 ? void 0 : value.addressing.map((t) => (react_1.default.createElement(TagChip_1.default, { key: t.id, tag: t, onDelete: handleDeleteTag(t.id), icon: react_1.default.createElement(Icon_1.default, null, "label"), onClick: handleClickTag })))),
40
- (value === null || value === void 0 ? void 0 : value.location) && (react_1.default.createElement(material_1.Chip, { icon: react_1.default.createElement(Icon_1.default, null, "add_location_alt"), label: value === null || value === void 0 ? void 0 : value.location.location, onDelete: () => null, onClick: () => null }))));
46
+ (value === null || value === void 0 ? void 0 : value.location) && (react_1.default.createElement(material_1.Chip, { icon: react_1.default.createElement(Icon_1.default, null, "add_location_alt"), label: value === null || value === void 0 ? void 0 : value.location.location, onDelete: handleDeleteLocation, onClick: handleClickLocation }))));
41
47
  };
@@ -342,8 +342,11 @@ function Composer(inProps) {
342
342
  case 'addressing':
343
343
  handleAddAudienceLayer();
344
344
  break;
345
+ case 'location':
346
+ handleAddLocationLayer();
347
+ break;
345
348
  }
346
- }, [handleAddCategoryLayer, handleAddAudienceLayer]);
349
+ }, [handleAddCategoryLayer, handleAddAudienceLayer, handleAddLocationLayer]);
347
350
  const handleSubmit = (0, react_1.useCallback)((event) => {
348
351
  event.preventDefault();
349
352
  event.stopPropagation();
@@ -476,7 +479,7 @@ function Composer(inProps) {
476
479
  react_1.default.createElement(material_1.IconButton, { disabled: isSubmitting, onClick: handleAddCategoryLayer },
477
480
  react_1.default.createElement(Icon_1.default, null, "category")),
478
481
  react_1.default.createElement(material_1.IconButton, { disabled: isSubmitting || !features.includes(types_1.SCFeatureName.TAGGING), onClick: handleAddAudienceLayer }, addressing === null || addressing.length === 0 ? react_1.default.createElement(Icon_1.default, null, "public") : react_1.default.createElement(Icon_1.default, null, "label")),
479
- preferences[react_core_1.SCPreferences.ADDONS_POST_GEOLOCATION_ENABLED] && (react_1.default.createElement(material_1.IconButton, { disabled: isSubmitting, onClick: handleAddLocationLayer, color: location !== null ? 'primary' : 'default' },
482
+ preferences[react_core_1.SCPreferences.ADDONS_POST_GEOLOCATION_ENABLED].value && (react_1.default.createElement(material_1.IconButton, { disabled: isSubmitting, onClick: handleAddLocationLayer, color: location !== null ? 'primary' : 'default' },
480
483
  react_1.default.createElement(Icon_1.default, null, "add_location_alt"))))),
481
484
  layer && react_1.default.createElement(LayerTransitionRoot, { className: classes.layerTransitionRoot, in: true, container: dialogRef.current, direction: "left" },
482
485
  react_1.default.createElement(layer.Component, Object.assign({}, layer.ComponentProps)))));
@@ -88,16 +88,22 @@ function LocationAutocomplete(inProps) {
88
88
  }, [value]);
89
89
  // Handlers
90
90
  const handleChange = (event, value) => {
91
- setValue({ location: value.full_address, lat: value.lat, lon: value.lng });
91
+ setValue(value ? { location: value.full_address, lat: value.lat, lng: value.lng } : null);
92
92
  onChange && onChange(value);
93
93
  };
94
94
  const handleSearch = (event, _search) => {
95
95
  setSearch(_search);
96
96
  };
97
97
  // Render
98
- return (react_1.default.createElement(Root, Object.assign({ className: classes.root, options: locations || [],
98
+ const options = (0, react_1.useMemo)(() => {
99
+ if (!value || typeof value === 'string' || locations.find((loc) => value.lat === loc.lat && value.lng === loc.lng)) {
100
+ return locations;
101
+ }
102
+ return [...locations, { lat: value.lat, lng: value.lng, full_address: value.location }];
103
+ }, [value, locations]);
104
+ return (react_1.default.createElement(Root, Object.assign({ className: classes.root, options: options || [],
99
105
  // @ts-ignore
100
- getOptionLabel: (option) => (option === null || option === void 0 ? void 0 : option.full_address) || (option === null || option === void 0 ? void 0 : option.location) || '', filterOptions: (x) => x, autoComplete: true, includeInputInList: true, filterSelectedOptions: true, value: value, selectOnFocus: true, handleHomeEndKeys: true, disabled: disabled, noOptionsText: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.locationAutocomplete.empty", defaultMessage: "ui.locationAutocomplete.empty" }), onChange: handleChange, onInputChange: handleSearch, isOptionEqualToValue: (option, value) => value.lat === option.lat && value.lon === option.lng, renderInput: (params) => {
106
+ getOptionLabel: (option) => (option === null || option === void 0 ? void 0 : option.full_address) || (option === null || option === void 0 ? void 0 : option.location) || '', filterOptions: (x) => x, autoComplete: true, includeInputInList: true, value: value || null, selectOnFocus: true, handleHomeEndKeys: true, disabled: disabled, noOptionsText: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.locationAutocomplete.empty", defaultMessage: "ui.locationAutocomplete.empty" }), onChange: handleChange, onInputChange: handleSearch, isOptionEqualToValue: (option, value) => value.lat === option.lat && value.lng === option.lng, renderInput: (params) => {
101
107
  return (react_1.default.createElement(TextField_1.default, Object.assign({}, params, TextFieldProps, { margin: "dense", InputProps: Object.assign(Object.assign({}, params.InputProps), { autoComplete: 'location', endAdornment: (react_1.default.createElement(react_1.default.Fragment, null,
102
108
  isLoading ? react_1.default.createElement(CircularProgress_1.default, { color: "inherit", size: 20 }) : null,
103
109
  params.InputProps.endAdornment)) }) })));
@@ -98,21 +98,6 @@ function PrivateMessageThread(inProps) {
98
98
  const { userObj, openNewMessage = false, onNewMessageClose = null, onNewMessageSent = null, onSingleMessageOpen = null, className } = props, rest = tslib_1.__rest(props, ["userObj", "openNewMessage", "onNewMessageClose", "onNewMessageSent", "onSingleMessageOpen", "className"]);
99
99
  // CONTEXT
100
100
  const scUserContext = (0, react_1.useContext)(react_core_1.SCUserContext);
101
- const role = react_core_1.UserUtils.getUserRole(scUserContext['user']);
102
- const scPreferencesContext = (0, react_core_1.useSCPreferences)();
103
- const followEnabled = (0, react_1.useMemo)(() => react_core_1.SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED in scPreferencesContext.preferences &&
104
- scPreferencesContext.preferences[react_core_1.SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED].value, [scPreferencesContext.preferences]);
105
- const manager = followEnabled
106
- ? scUserContext.managers.followers
107
- : scUserContext.managers.connections;
108
- function checkFollowerOrConnection(user) {
109
- if ('isFollower' in manager) {
110
- return manager.isFollower(user);
111
- }
112
- // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
113
- // @ts-ignore
114
- return manager.status(user);
115
- }
116
101
  // STATE
117
102
  const [value, setValue] = (0, react_1.useState)('');
118
103
  const [previous, setPrevious] = (0, react_1.useState)(null);
@@ -121,7 +106,6 @@ function PrivateMessageThread(inProps) {
121
106
  const [loading, setLoading] = (0, react_1.useState)(false);
122
107
  const [isHovered, setIsHovered] = (0, react_1.useState)({});
123
108
  const [followers, setFollowers] = (0, react_1.useState)([]);
124
- const [isFollower, setIsFollower] = (0, react_1.useState)(false);
125
109
  const isNew = userObj && userObj === types_1.SCPrivateMessageStatusType.NEW;
126
110
  const authUserId = scUserContext.user ? scUserContext.user.id : null;
127
111
  const [singleMessageUser, setSingleMessageUser] = (0, react_1.useState)(null);
@@ -274,7 +258,6 @@ function PrivateMessageThread(inProps) {
274
258
  function fetchThread() {
275
259
  if (userObj && typeof userObj !== 'string') {
276
260
  setLoadingMessageObjs(true);
277
- const _isFollower = (scUser && checkFollowerOrConnection(scUser)) || (scUser && scUser.community_badge);
278
261
  const _userObjId = isNumber ? userObj : messageReceiver(userObj, authUserId);
279
262
  api_services_1.PrivateMessageService.getAThread({ user: _userObjId, limit: 10 })
280
263
  .then((res) => {
@@ -290,7 +273,7 @@ function PrivateMessageThread(inProps) {
290
273
  setSingleMessageThread(false);
291
274
  }
292
275
  else {
293
- if (role || _isFollower || react_core_1.UserUtils.getUserRole(scUser)) {
276
+ if (scUser === null || scUser === void 0 ? void 0 : scUser.can_send_pm_to) {
294
277
  setSingleMessageThread(true);
295
278
  setRecipients(_userObjId);
296
279
  onSingleMessageOpen(true);
@@ -308,6 +291,9 @@ function PrivateMessageThread(inProps) {
308
291
  utils_1.Logger.error(Errors_1.SCOPE_SC_UI, { error });
309
292
  });
310
293
  }
294
+ else {
295
+ setSingleMessageUser(scUser);
296
+ }
311
297
  }
312
298
  const isNewerThan60Seconds = (creationTime) => {
313
299
  const date = new Date(creationTime);
@@ -415,14 +401,6 @@ function PrivateMessageThread(inProps) {
415
401
  fetchResults();
416
402
  }
417
403
  }, [value]);
418
- /**
419
- * Checks is thread receiver is a user follower
420
- */
421
- (0, react_1.useEffect)(() => {
422
- if (receiver) {
423
- !receiver.community_badge && scUser ? setIsFollower(checkFollowerOrConnection(scUser)) : setIsFollower(true);
424
- }
425
- });
426
404
  /**
427
405
  * On mount, if obj, fetches thread
428
406
  */
@@ -482,7 +460,7 @@ function PrivateMessageThread(inProps) {
482
460
  onMouseEnter: () => handleMouseEnter(msg.id),
483
461
  onMouseLeave: () => handleMouseLeave(msg.id)
484
462
  }, isHovering: isHovered[msg.id], showMenuIcon: authUserId === msg.sender.id, onMenuIconClick: () => handleOpenDeleteMessageDialog(msg) }))))))))),
485
- react_1.default.createElement(PrivateMessageEditor_1.default, { className: classes.editor, send: handleSend, autoHide: !isFollower && (!role || !react_core_1.UserUtils.getUserRole(scUser)), autoHideDeletion: (receiver === null || receiver === void 0 ? void 0 : receiver.deleted) || (scUser === null || scUser === void 0 ? void 0 : scUser.deleted), onThreadChangeId: isNumber ? userObj : userObj.receiver.id, error: error, onErrorRemove: () => setError(false) }),
463
+ react_1.default.createElement(PrivateMessageEditor_1.default, { className: classes.editor, send: handleSend, autoHide: !(scUser === null || scUser === void 0 ? void 0 : scUser.can_send_pm_to), autoHideDeletion: (receiver === null || receiver === void 0 ? void 0 : receiver.deleted) || (scUser === null || scUser === void 0 ? void 0 : scUser.deleted), onThreadChangeId: isNumber ? userObj : userObj.receiver.id, error: error, onErrorRemove: () => setError(false) }),
486
464
  openDeleteMessageDialog && (react_1.default.createElement(ConfirmDialog_1.default, { open: openDeleteMessageDialog, title: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.privateMessage.component.delete.message.dialog.msg", defaultMessage: "ui.privateMessage.component.delete.message.dialog.msg" }), btnConfirm: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.privateMessage.component.delete.message.dialog.confirm", defaultMessage: "ui.privateMessage.component.delete.message.dialog.confirm" }), onConfirm: handleDeleteMessage, onClose: handleCloseDeleteMessageDialog }))));
487
465
  }
488
466
  /**
@@ -121,6 +121,11 @@ function PrivateMessageThreadItem(inProps) {
121
121
  return null;
122
122
  }
123
123
  let section = null;
124
+ const defaultSection = (react_1.default.createElement(material_1.Box, { className: classes.other },
125
+ react_1.default.createElement(material_1.Button, { onClick: () => handleDownload(m.file) },
126
+ react_1.default.createElement(Icon_1.default, null, "download"),
127
+ react_1.default.createElement(material_1.Typography, null, m.file.filename),
128
+ react_1.default.createElement(material_1.Typography, null, (0, sizeCoverter_1.bytesToSize)(m.file.filesize)))));
124
129
  if (m.file) {
125
130
  let type = m.file.mimetype;
126
131
  switch (true) {
@@ -129,11 +134,15 @@ function PrivateMessageThreadItem(inProps) {
129
134
  react_1.default.createElement("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img', onClick: () => setOpenDialog(true) })));
130
135
  break;
131
136
  case type.startsWith(types_1.SCMessageFileType.VIDEO):
132
- section = (react_1.default.createElement(material_1.Box, { className: (0, classnames_1.default)(classes.img, classes.video) },
133
- react_1.default.createElement("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img' }),
134
- !(0, thumbnailCoverter_1.isSupportedVideoFormat)(m.file.filename) ? (react_1.default.createElement(material_1.Button, { onClick: () => handleDownload(m.file), className: classes.iconButton },
135
- react_1.default.createElement(Icon_1.default, null, "download"))) : (react_1.default.createElement(material_1.IconButton, { onClick: () => setOpenDialog(true) },
136
- react_1.default.createElement(Icon_1.default, null, "play_circle_outline")))));
137
+ if (!(0, thumbnailCoverter_1.isSupportedVideoFormat)(m.file.filename)) {
138
+ section = defaultSection;
139
+ }
140
+ else {
141
+ section = (react_1.default.createElement(material_1.Box, { className: (0, classnames_1.default)(classes.img, classes.video) },
142
+ react_1.default.createElement("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img' }),
143
+ react_1.default.createElement(material_1.IconButton, { onClick: () => setOpenDialog(true) },
144
+ react_1.default.createElement(Icon_1.default, null, "play_circle_outline"))));
145
+ }
137
146
  break;
138
147
  case type.startsWith(types_1.SCMessageFileType.DOCUMENT):
139
148
  section = (react_1.default.createElement(material_1.Box, { className: m.file.filename.endsWith('.pdf') ? classes.document : classes.other },
@@ -145,11 +154,7 @@ function PrivateMessageThreadItem(inProps) {
145
154
  break;
146
155
  default:
147
156
  // section = <Icon>hide_image</Icon>;
148
- section = (react_1.default.createElement(material_1.Box, { className: classes.other },
149
- react_1.default.createElement(material_1.Button, { onClick: () => handleDownload(m.file) },
150
- react_1.default.createElement(Icon_1.default, null, "download"),
151
- react_1.default.createElement(material_1.Typography, null, m.file.filename),
152
- react_1.default.createElement(material_1.Typography, null, (0, sizeCoverter_1.bytesToSize)(m.file.filesize)))));
157
+ section = defaultSection;
153
158
  break;
154
159
  }
155
160
  }
@@ -10,9 +10,11 @@ const react_sortablejs_1 = require("react-sortablejs");
10
10
  const DisplayComponent_1 = tslib_1.__importDefault(require("./DisplayComponent"));
11
11
  const constants_1 = require("./constants");
12
12
  const filter_1 = tslib_1.__importDefault(require("./filter"));
13
+ const Media_1 = require("../../../constants/Media");
13
14
  const classes = {
14
15
  previewRoot: `${constants_1.PREFIX}-preview-root`,
15
16
  media: `${constants_1.PREFIX}-media`,
17
+ video: `${constants_1.PREFIX}-media-video`,
16
18
  delete: `${constants_1.PREFIX}-delete`
17
19
  };
18
20
  const Root = (0, styles_1.styled)(material_1.Box, {
@@ -29,7 +31,7 @@ const PreviewComponent = react_1.default.forwardRef((props, ref) => {
29
31
  onChange && onChange([...value.filter((media) => medias.findIndex((m) => m.id === media.id) === -1), ...medias]);
30
32
  }, [onChange, value]);
31
33
  const handleDelete = (0, react_1.useCallback)((id) => () => onChange && onChange(value.filter((media) => media.id !== id)), [onChange, value]);
32
- return react_1.default.createElement(Root, Object.assign({ ref: ref, className: (0, classnames_1.default)(className, classes.previewRoot) }, rest), medias.length > 0 && (react_1.default.createElement(react_sortablejs_1.ReactSortable, { list: medias, setList: handleSort }, medias.map((media) => (react_1.default.createElement(material_1.Box, { key: media.id, className: classes.media },
34
+ return react_1.default.createElement(Root, Object.assign({ ref: ref, className: (0, classnames_1.default)(className, classes.previewRoot) }, rest), medias.length > 0 && (react_1.default.createElement(react_sortablejs_1.ReactSortable, { list: medias, setList: handleSort }, medias.map((media) => (react_1.default.createElement(material_1.Box, { key: media.id, className: (0, classnames_1.default)(classes.media, { [classes.video]: media.embed.metadata && media.embed.metadata.type === Media_1.MEDIA_TYPE_VIDEO }) },
33
35
  react_1.default.createElement(DisplayComponent_1.default, { medias: [media] }),
34
36
  react_1.default.createElement(material_1.IconButton, { className: classes.delete, onClick: handleDelete(media.id), size: "small" },
35
37
  react_1.default.createElement(Icon_1.default, null, "delete"))))))));
@@ -16,7 +16,7 @@ export interface AttributesProps extends Omit<BoxProps, 'value' | 'onChange' | '
16
16
  * @param value
17
17
  * @default empty object
18
18
  */
19
- onClick?: (attribute: 'categories' | 'addressing') => void;
19
+ onClick?: (attribute: 'categories' | 'addressing' | 'location') => void;
20
20
  }
21
21
  declare const _default: (props: AttributesProps) => JSX.Element;
22
22
  export default _default;
@@ -29,10 +29,16 @@ export default (props) => {
29
29
  const handleClickTag = useCallback(() => {
30
30
  onClick && onClick('addressing');
31
31
  }, [onClick]);
32
+ const handleDeleteLocation = useCallback(() => {
33
+ onChange && onChange(Object.assign(Object.assign({}, value), { location: null }));
34
+ }, [value, onChange]);
35
+ const handleClickLocation = useCallback(() => {
36
+ onClick && onClick('location');
37
+ }, [onClick]);
32
38
  return (React.createElement(Root, { className: classNames(classes.root, className) },
33
39
  ((_a = value === null || value === void 0 ? void 0 : value.categories) === null || _a === void 0 ? void 0 : _a.length) > 0 &&
34
40
  (value === null || value === void 0 ? void 0 : value.categories.map((c) => (React.createElement(Chip, { key: c.id, label: c.name, onDelete: handleDeleteCategory(c.id), icon: React.createElement(Icon, null, "category"), onClick: handleClickCategory })))),
35
41
  ((_b = value === null || value === void 0 ? void 0 : value.addressing) === null || _b === void 0 ? void 0 : _b.length) > 0 &&
36
42
  (value === null || value === void 0 ? void 0 : value.addressing.map((t) => (React.createElement(TagChip, { key: t.id, tag: t, onDelete: handleDeleteTag(t.id), icon: React.createElement(Icon, null, "label"), onClick: handleClickTag })))),
37
- (value === null || value === void 0 ? void 0 : value.location) && (React.createElement(Chip, { icon: React.createElement(Icon, null, "add_location_alt"), label: value === null || value === void 0 ? void 0 : value.location.location, onDelete: () => null, onClick: () => null }))));
43
+ (value === null || value === void 0 ? void 0 : value.location) && (React.createElement(Chip, { icon: React.createElement(Icon, null, "add_location_alt"), label: value === null || value === void 0 ? void 0 : value.location.location, onDelete: handleDeleteLocation, onClick: handleClickLocation }))));
38
44
  };
@@ -340,8 +340,11 @@ export default function Composer(inProps) {
340
340
  case 'addressing':
341
341
  handleAddAudienceLayer();
342
342
  break;
343
+ case 'location':
344
+ handleAddLocationLayer();
345
+ break;
343
346
  }
344
- }, [handleAddCategoryLayer, handleAddAudienceLayer]);
347
+ }, [handleAddCategoryLayer, handleAddAudienceLayer, handleAddLocationLayer]);
345
348
  const handleSubmit = useCallback((event) => {
346
349
  event.preventDefault();
347
350
  event.stopPropagation();
@@ -474,7 +477,7 @@ export default function Composer(inProps) {
474
477
  React.createElement(IconButton, { disabled: isSubmitting, onClick: handleAddCategoryLayer },
475
478
  React.createElement(Icon, null, "category")),
476
479
  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")),
477
- preferences[SCPreferences.ADDONS_POST_GEOLOCATION_ENABLED] && (React.createElement(IconButton, { disabled: isSubmitting, onClick: handleAddLocationLayer, color: location !== null ? 'primary' : 'default' },
480
+ preferences[SCPreferences.ADDONS_POST_GEOLOCATION_ENABLED].value && (React.createElement(IconButton, { disabled: isSubmitting, onClick: handleAddLocationLayer, color: location !== null ? 'primary' : 'default' },
478
481
  React.createElement(Icon, null, "add_location_alt"))))),
479
482
  layer && React.createElement(LayerTransitionRoot, { className: classes.layerTransitionRoot, in: true, container: dialogRef.current, direction: "left" },
480
483
  React.createElement(layer.Component, Object.assign({}, layer.ComponentProps)))));
@@ -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 { FormattedMessage } from 'react-intl';
4
4
  import TextField from '@mui/material/TextField';
5
5
  import CircularProgress from '@mui/material/CircularProgress';
@@ -86,16 +86,22 @@ export default function LocationAutocomplete(inProps) {
86
86
  }, [value]);
87
87
  // Handlers
88
88
  const handleChange = (event, value) => {
89
- setValue({ location: value.full_address, lat: value.lat, lon: value.lng });
89
+ setValue(value ? { location: value.full_address, lat: value.lat, lng: value.lng } : null);
90
90
  onChange && onChange(value);
91
91
  };
92
92
  const handleSearch = (event, _search) => {
93
93
  setSearch(_search);
94
94
  };
95
95
  // Render
96
- return (React.createElement(Root, Object.assign({ className: classes.root, options: locations || [],
96
+ const options = useMemo(() => {
97
+ if (!value || typeof value === 'string' || locations.find((loc) => value.lat === loc.lat && value.lng === loc.lng)) {
98
+ return locations;
99
+ }
100
+ return [...locations, { lat: value.lat, lng: value.lng, full_address: value.location }];
101
+ }, [value, locations]);
102
+ return (React.createElement(Root, Object.assign({ className: classes.root, options: options || [],
97
103
  // @ts-ignore
98
- getOptionLabel: (option) => (option === null || option === void 0 ? void 0 : option.full_address) || (option === null || option === void 0 ? void 0 : option.location) || '', filterOptions: (x) => x, autoComplete: true, includeInputInList: true, filterSelectedOptions: true, value: value, selectOnFocus: true, handleHomeEndKeys: true, disabled: disabled, noOptionsText: React.createElement(FormattedMessage, { id: "ui.locationAutocomplete.empty", defaultMessage: "ui.locationAutocomplete.empty" }), onChange: handleChange, onInputChange: handleSearch, isOptionEqualToValue: (option, value) => value.lat === option.lat && value.lon === option.lng, renderInput: (params) => {
104
+ getOptionLabel: (option) => (option === null || option === void 0 ? void 0 : option.full_address) || (option === null || option === void 0 ? void 0 : option.location) || '', filterOptions: (x) => x, autoComplete: true, includeInputInList: true, value: value || null, selectOnFocus: true, handleHomeEndKeys: true, disabled: disabled, noOptionsText: React.createElement(FormattedMessage, { id: "ui.locationAutocomplete.empty", defaultMessage: "ui.locationAutocomplete.empty" }), onChange: handleChange, onInputChange: handleSearch, isOptionEqualToValue: (option, value) => value.lat === option.lat && value.lng === option.lng, renderInput: (params) => {
99
105
  return (React.createElement(TextField, Object.assign({}, params, TextFieldProps, { margin: "dense", InputProps: Object.assign(Object.assign({}, params.InputProps), { autoComplete: 'location', endAdornment: (React.createElement(React.Fragment, null,
100
106
  isLoading ? React.createElement(CircularProgress, { color: "inherit", size: 20 }) : null,
101
107
  params.InputProps.endAdornment)) }) })));
@@ -2,7 +2,7 @@ import { __rest } from "tslib";
2
2
  import React, { useCallback, useContext, useEffect, useMemo, useRef, useState } from 'react';
3
3
  import { styled } from '@mui/material/styles';
4
4
  import { Endpoints, http, PrivateMessageService } from '@selfcommunity/api-services';
5
- import { SCPreferences, SCUserContext, UserUtils, useSCFetchUser, useSCPreferences } from '@selfcommunity/react-core';
5
+ import { SCUserContext, UserUtils, useSCFetchUser } from '@selfcommunity/react-core';
6
6
  import { SCNotificationTopicType, SCNotificationTypologyType, SCPrivateMessageStatusType } from '@selfcommunity/types';
7
7
  import PrivateMessageThreadItem, { PrivateMessageThreadItemSkeleton } from '../PrivateMessageThreadItem';
8
8
  import PubSub from 'pubsub-js';
@@ -96,21 +96,6 @@ export default function PrivateMessageThread(inProps) {
96
96
  const { userObj, openNewMessage = false, onNewMessageClose = null, onNewMessageSent = null, onSingleMessageOpen = null, className } = props, rest = __rest(props, ["userObj", "openNewMessage", "onNewMessageClose", "onNewMessageSent", "onSingleMessageOpen", "className"]);
97
97
  // CONTEXT
98
98
  const scUserContext = useContext(SCUserContext);
99
- const role = UserUtils.getUserRole(scUserContext['user']);
100
- const scPreferencesContext = useSCPreferences();
101
- const followEnabled = useMemo(() => SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED in scPreferencesContext.preferences &&
102
- scPreferencesContext.preferences[SCPreferences.CONFIGURATIONS_FOLLOW_ENABLED].value, [scPreferencesContext.preferences]);
103
- const manager = followEnabled
104
- ? scUserContext.managers.followers
105
- : scUserContext.managers.connections;
106
- function checkFollowerOrConnection(user) {
107
- if ('isFollower' in manager) {
108
- return manager.isFollower(user);
109
- }
110
- // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
111
- // @ts-ignore
112
- return manager.status(user);
113
- }
114
99
  // STATE
115
100
  const [value, setValue] = useState('');
116
101
  const [previous, setPrevious] = useState(null);
@@ -119,7 +104,6 @@ export default function PrivateMessageThread(inProps) {
119
104
  const [loading, setLoading] = useState(false);
120
105
  const [isHovered, setIsHovered] = useState({});
121
106
  const [followers, setFollowers] = useState([]);
122
- const [isFollower, setIsFollower] = useState(false);
123
107
  const isNew = userObj && userObj === SCPrivateMessageStatusType.NEW;
124
108
  const authUserId = scUserContext.user ? scUserContext.user.id : null;
125
109
  const [singleMessageUser, setSingleMessageUser] = useState(null);
@@ -272,7 +256,6 @@ export default function PrivateMessageThread(inProps) {
272
256
  function fetchThread() {
273
257
  if (userObj && typeof userObj !== 'string') {
274
258
  setLoadingMessageObjs(true);
275
- const _isFollower = (scUser && checkFollowerOrConnection(scUser)) || (scUser && scUser.community_badge);
276
259
  const _userObjId = isNumber ? userObj : messageReceiver(userObj, authUserId);
277
260
  PrivateMessageService.getAThread({ user: _userObjId, limit: 10 })
278
261
  .then((res) => {
@@ -288,7 +271,7 @@ export default function PrivateMessageThread(inProps) {
288
271
  setSingleMessageThread(false);
289
272
  }
290
273
  else {
291
- if (role || _isFollower || UserUtils.getUserRole(scUser)) {
274
+ if (scUser === null || scUser === void 0 ? void 0 : scUser.can_send_pm_to) {
292
275
  setSingleMessageThread(true);
293
276
  setRecipients(_userObjId);
294
277
  onSingleMessageOpen(true);
@@ -306,6 +289,9 @@ export default function PrivateMessageThread(inProps) {
306
289
  Logger.error(SCOPE_SC_UI, { error });
307
290
  });
308
291
  }
292
+ else {
293
+ setSingleMessageUser(scUser);
294
+ }
309
295
  }
310
296
  const isNewerThan60Seconds = (creationTime) => {
311
297
  const date = new Date(creationTime);
@@ -413,14 +399,6 @@ export default function PrivateMessageThread(inProps) {
413
399
  fetchResults();
414
400
  }
415
401
  }, [value]);
416
- /**
417
- * Checks is thread receiver is a user follower
418
- */
419
- useEffect(() => {
420
- if (receiver) {
421
- !receiver.community_badge && scUser ? setIsFollower(checkFollowerOrConnection(scUser)) : setIsFollower(true);
422
- }
423
- });
424
402
  /**
425
403
  * On mount, if obj, fetches thread
426
404
  */
@@ -480,7 +458,7 @@ export default function PrivateMessageThread(inProps) {
480
458
  onMouseEnter: () => handleMouseEnter(msg.id),
481
459
  onMouseLeave: () => handleMouseLeave(msg.id)
482
460
  }, isHovering: isHovered[msg.id], showMenuIcon: authUserId === msg.sender.id, onMenuIconClick: () => handleOpenDeleteMessageDialog(msg) }))))))))),
483
- React.createElement(PrivateMessageEditor, { className: classes.editor, send: handleSend, autoHide: !isFollower && (!role || !UserUtils.getUserRole(scUser)), autoHideDeletion: (receiver === null || receiver === void 0 ? void 0 : receiver.deleted) || (scUser === null || scUser === void 0 ? void 0 : scUser.deleted), onThreadChangeId: isNumber ? userObj : userObj.receiver.id, error: error, onErrorRemove: () => setError(false) }),
461
+ React.createElement(PrivateMessageEditor, { className: classes.editor, send: handleSend, autoHide: !(scUser === null || scUser === void 0 ? void 0 : scUser.can_send_pm_to), autoHideDeletion: (receiver === null || receiver === void 0 ? void 0 : receiver.deleted) || (scUser === null || scUser === void 0 ? void 0 : scUser.deleted), onThreadChangeId: isNumber ? userObj : userObj.receiver.id, error: error, onErrorRemove: () => setError(false) }),
484
462
  openDeleteMessageDialog && (React.createElement(ConfirmDialog, { open: openDeleteMessageDialog, title: React.createElement(FormattedMessage, { id: "ui.privateMessage.component.delete.message.dialog.msg", defaultMessage: "ui.privateMessage.component.delete.message.dialog.msg" }), btnConfirm: React.createElement(FormattedMessage, { id: "ui.privateMessage.component.delete.message.dialog.confirm", defaultMessage: "ui.privateMessage.component.delete.message.dialog.confirm" }), onConfirm: handleDeleteMessage, onClose: handleCloseDeleteMessageDialog }))));
485
463
  }
486
464
  /**
@@ -119,6 +119,11 @@ export default function PrivateMessageThreadItem(inProps) {
119
119
  return null;
120
120
  }
121
121
  let section = null;
122
+ const defaultSection = (React.createElement(Box, { className: classes.other },
123
+ React.createElement(Button, { onClick: () => handleDownload(m.file) },
124
+ React.createElement(Icon, null, "download"),
125
+ React.createElement(Typography, null, m.file.filename),
126
+ React.createElement(Typography, null, bytesToSize(m.file.filesize)))));
122
127
  if (m.file) {
123
128
  let type = m.file.mimetype;
124
129
  switch (true) {
@@ -127,11 +132,15 @@ export default function PrivateMessageThreadItem(inProps) {
127
132
  React.createElement("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img', onClick: () => setOpenDialog(true) })));
128
133
  break;
129
134
  case type.startsWith(SCMessageFileType.VIDEO):
130
- section = (React.createElement(Box, { className: classNames(classes.img, classes.video) },
131
- React.createElement("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img' }),
132
- !isSupportedVideoFormat(m.file.filename) ? (React.createElement(Button, { onClick: () => handleDownload(m.file), className: classes.iconButton },
133
- React.createElement(Icon, null, "download"))) : (React.createElement(IconButton, { onClick: () => setOpenDialog(true) },
134
- React.createElement(Icon, null, "play_circle_outline")))));
135
+ if (!isSupportedVideoFormat(m.file.filename)) {
136
+ section = defaultSection;
137
+ }
138
+ else {
139
+ section = (React.createElement(Box, { className: classNames(classes.img, classes.video) },
140
+ React.createElement("img", { src: m.file.thumbnail, loading: "lazy", alt: 'img' }),
141
+ React.createElement(IconButton, { onClick: () => setOpenDialog(true) },
142
+ React.createElement(Icon, null, "play_circle_outline"))));
143
+ }
135
144
  break;
136
145
  case type.startsWith(SCMessageFileType.DOCUMENT):
137
146
  section = (React.createElement(Box, { className: m.file.filename.endsWith('.pdf') ? classes.document : classes.other },
@@ -143,11 +152,7 @@ export default function PrivateMessageThreadItem(inProps) {
143
152
  break;
144
153
  default:
145
154
  // section = <Icon>hide_image</Icon>;
146
- section = (React.createElement(Box, { className: classes.other },
147
- React.createElement(Button, { onClick: () => handleDownload(m.file) },
148
- React.createElement(Icon, null, "download"),
149
- React.createElement(Typography, null, m.file.filename),
150
- React.createElement(Typography, null, bytesToSize(m.file.filesize)))));
155
+ section = defaultSection;
151
156
  break;
152
157
  }
153
158
  }
@@ -8,9 +8,11 @@ import { ReactSortable } from 'react-sortablejs';
8
8
  import DisplayComponent from './DisplayComponent';
9
9
  import { PREFIX } from './constants';
10
10
  import filter from './filter';
11
+ import { MEDIA_TYPE_VIDEO } from '../../../constants/Media';
11
12
  const classes = {
12
13
  previewRoot: `${PREFIX}-preview-root`,
13
14
  media: `${PREFIX}-media`,
15
+ video: `${PREFIX}-media-video`,
14
16
  delete: `${PREFIX}-delete`
15
17
  };
16
18
  const Root = styled(Box, {
@@ -27,7 +29,7 @@ const PreviewComponent = React.forwardRef((props, ref) => {
27
29
  onChange && onChange([...value.filter((media) => medias.findIndex((m) => m.id === media.id) === -1), ...medias]);
28
30
  }, [onChange, value]);
29
31
  const handleDelete = useCallback((id) => () => onChange && onChange(value.filter((media) => media.id !== id)), [onChange, value]);
30
- return React.createElement(Root, Object.assign({ ref: ref, className: classNames(className, classes.previewRoot) }, rest), medias.length > 0 && (React.createElement(ReactSortable, { list: medias, setList: handleSort }, medias.map((media) => (React.createElement(Box, { key: media.id, className: classes.media },
32
+ return React.createElement(Root, Object.assign({ ref: ref, className: classNames(className, classes.previewRoot) }, rest), medias.length > 0 && (React.createElement(ReactSortable, { list: medias, setList: handleSort }, medias.map((media) => (React.createElement(Box, { key: media.id, className: classNames(classes.media, { [classes.video]: media.embed.metadata && media.embed.metadata.type === MEDIA_TYPE_VIDEO }) },
31
33
  React.createElement(DisplayComponent, { medias: [media] }),
32
34
  React.createElement(IconButton, { className: classes.delete, onClick: handleDelete(media.id), size: "small" },
33
35
  React.createElement(Icon, null, "delete"))))))));