@selfcommunity/react-ui 0.11.0-alpha.83 → 0.11.0-alpha.85

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.
@@ -15,7 +15,7 @@ const Root = (0, material_1.styled)(material_1.Box, {
15
15
  slot: 'AttributesRoot'
16
16
  })(() => ({}));
17
17
  exports.default = (props) => {
18
- var _a, _b, _c, _d;
18
+ var _a, _b, _c, _d, _e;
19
19
  // PROPS
20
20
  const { className = null, value = null, onChange = null, onClick = null } = props;
21
21
  // HANDLERS
@@ -49,13 +49,16 @@ exports.default = (props) => {
49
49
  const handleClickLocation = (0, react_1.useCallback)(() => {
50
50
  onClick && onClick('location');
51
51
  }, [onClick]);
52
- const handleDeleteRecipient = (0, react_1.useCallback)((id) => () => {
53
- onChange && onChange(Object.assign(Object.assign({}, value), { recipients: value.recipients.filter((r) => r.id !== id) }));
52
+ const handleDeleteRecipient = (0, react_1.useCallback)((identifier) => () => {
53
+ if (!(value === null || value === void 0 ? void 0 : value.recipients))
54
+ return;
55
+ onChange &&
56
+ onChange(Object.assign(Object.assign({}, value), { recipients: value.recipients.filter((r) => typeof r === 'object' ? r.id !== identifier : r !== identifier) }));
54
57
  }, [value, onChange]);
55
58
  const handleClickRecipient = (0, react_1.useCallback)(() => {
56
59
  onClick && onClick('recipients');
57
60
  }, [onClick]);
58
61
  return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, { children: [((_a = value === null || value === void 0 ? void 0 : value.categories) === null || _a === void 0 ? void 0 : _a.length) > 0 &&
59
62
  (value === null || value === void 0 ? void 0 : value.categories.map((c) => ((0, jsx_runtime_1.jsx)(material_1.Chip, { label: c.name, onDelete: handleDeleteCategory(c.id), icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "category" }), onClick: handleClickCategory }, c.id)))), (value === null || value === void 0 ? void 0 : value.group) && ((0, jsx_runtime_1.jsx)(material_1.Chip, { label: value === null || value === void 0 ? void 0 : value.group.name, onDelete: handleDeleteGroup, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "groups" }), onClick: handleClickGroup, disabled: !((_b = value === null || value === void 0 ? void 0 : value.group) === null || _b === void 0 ? void 0 : _b.subscription_status) }, value === null || value === void 0 ? void 0 : value.group.id)), (value === null || value === void 0 ? void 0 : value.event) && ((0, jsx_runtime_1.jsx)(material_1.Chip, { label: value === null || value === void 0 ? void 0 : value.event.name, onDelete: handleDeleteEvent, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "CalendarIcon" }), onClick: handleClickEvent, disabled: !((_c = value === null || value === void 0 ? void 0 : value.event) === null || _c === void 0 ? void 0 : _c.subscription_status) }, value === null || value === void 0 ? void 0 : value.event.id)), ((_d = value === null || value === void 0 ? void 0 : value.addressing) === null || _d === void 0 ? void 0 : _d.length) > 0 &&
60
- (value === null || value === void 0 ? void 0 : value.addressing.map((t) => ((0, jsx_runtime_1.jsx)(TagChip_1.default, { tag: t, onDelete: handleDeleteTag(t.id), icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "label" }), onClick: handleClickTag }, t.id)))), (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: (value === null || value === void 0 ? void 0 : value.recipients.length) > 0 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [value.recipients.slice(0, 3).map((r) => ((0, jsx_runtime_1.jsx)(material_1.Chip, { label: r.username, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "people_alt" }), onClick: handleClickRecipient, onDelete: handleDeleteRecipient(r.id) }, r.id))), value.recipients.length > 3 && (0, jsx_runtime_1.jsx)(material_1.Chip, { label: `+${value.recipients.length - 3}` })] })) }), (value === null || value === void 0 ? void 0 : value.location) && ((0, jsx_runtime_1.jsx)(material_1.Chip, { icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "add_location_alt" }), label: value === null || value === void 0 ? void 0 : value.location.location, onDelete: handleDeleteLocation, onClick: handleClickLocation }))] })));
63
+ (value === null || value === void 0 ? void 0 : value.addressing.map((t) => ((0, jsx_runtime_1.jsx)(TagChip_1.default, { tag: t, onDelete: handleDeleteTag(t.id), icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "label" }), onClick: handleClickTag }, t.id)))), (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: ((_e = value === null || value === void 0 ? void 0 : value.recipients) === null || _e === void 0 ? void 0 : _e.length) > 0 && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [value.recipients.slice(0, 3).map((r) => ((0, jsx_runtime_1.jsx)(material_1.Chip, { label: typeof r === 'object' ? r.username : r, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "people_alt" }), onClick: handleClickRecipient, onDelete: handleDeleteRecipient(typeof r === 'object' ? r.id : r) }, typeof r === 'object' ? r.id : r))), value.recipients.length > 3 && (0, jsx_runtime_1.jsx)(material_1.Chip, { label: `+${value.recipients.length - 3}` })] })) }), (value === null || value === void 0 ? void 0 : value.location) && ((0, jsx_runtime_1.jsx)(material_1.Chip, { icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "add_location_alt" }), label: value === null || value === void 0 ? void 0 : value.location.location, onDelete: handleDeleteLocation, onClick: handleClickLocation }))] })));
61
64
  };
@@ -159,6 +159,11 @@ function Composer(inProps) {
159
159
  const categoryRequiredEnabled = (0, react_1.useMemo)(() => preferences &&
160
160
  react_core_1.SCPreferences.CONFIGURATIONS_POST_CATEGORY_REQUIRED_ENABLED in preferences &&
161
161
  preferences[react_core_1.SCPreferences.CONFIGURATIONS_POST_CATEGORY_REQUIRED_ENABLED].value, [preferences]);
162
+ const usersTaggingEnabled = (0, react_1.useMemo)(() => preferences &&
163
+ features &&
164
+ features.includes(types_1.SCFeatureName.TAGGING) &&
165
+ react_core_1.SCPreferences.CONFIGURATIONS_POST_USER_ADDRESSING_ENABLED in preferences &&
166
+ preferences[react_core_1.SCPreferences.CONFIGURATIONS_POST_USER_ADDRESSING_ENABLED].value, [preferences, features]);
162
167
  const destructureFeedObject = (_feedObject) => {
163
168
  if (_feedObject.type === types_1.SCContributionType.POST) {
164
169
  _feedObject = _feedObject;
@@ -319,27 +324,31 @@ function Composer(inProps) {
319
324
  const handleChangeType = (0, react_1.useCallback)((value) => {
320
325
  dispatch({ type: 'type', value });
321
326
  }, []);
327
+ const getAddressingError = (content) => {
328
+ var _a, _b;
329
+ const isMissing = addressingRequiredEnabled && !((_a = content.addressing) === null || _a === void 0 ? void 0 : _a.length) && !((_b = content.recipients) === null || _b === void 0 ? void 0 : _b.length);
330
+ if (!isMissing)
331
+ return null;
332
+ return usersTaggingEnabled ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.addressingRecipients.error.missing", defaultMessage: "ui.composer.addressingRecipients.error.missing" })) : ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" }));
333
+ };
322
334
  const handleChangePoll = (0, react_1.useCallback)((content) => {
323
335
  dispatch({
324
336
  type: 'multiple',
325
337
  value: Object.assign(Object.assign({}, content), { pollError: content.poll.title.length > Composer_1.COMPOSER_TITLE_MAX_LENGTH
326
338
  ? { titleError: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.title.error.maxlength", defaultMessage: "ui.composer.title.error.maxlength" }) }
327
- : null, addressingError: addressingRequiredEnabled &&
328
- (!content.addressing || content.addressing.length === 0 || !content.recipients || content.recipients.length === 0) ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" })) : null })
339
+ : null, addressingError: getAddressingError(content) })
329
340
  });
330
341
  }, []);
331
342
  const handleChangeDiscussion = (0, react_1.useCallback)((content) => {
332
343
  dispatch({
333
344
  type: 'multiple',
334
- value: Object.assign(Object.assign({}, content), { titleError: content.title.length > Composer_1.COMPOSER_TITLE_MAX_LENGTH ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.title.error.maxlength", defaultMessage: "ui.composer.title.error.maxlength" })) : null, addressingError: addressingRequiredEnabled &&
335
- (!content.addressing || content.addressing.length === 0 || !content.recipients || content.recipients.length === 0) ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" })) : null, categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
345
+ value: Object.assign(Object.assign({}, content), { titleError: content.title.length > Composer_1.COMPOSER_TITLE_MAX_LENGTH ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.title.error.maxlength", defaultMessage: "ui.composer.title.error.maxlength" })) : null, addressingError: getAddressingError(content), categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
336
346
  });
337
347
  }, []);
338
348
  const handleChangePost = (0, react_1.useCallback)((content) => {
339
349
  dispatch({
340
350
  type: 'multiple',
341
- value: Object.assign(Object.assign({}, content), { addressingError: addressingRequiredEnabled &&
342
- (!content.addressing || content.addressing.length === 0 || !content.recipients || content.recipients.length === 0) ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" })) : null, categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
351
+ value: Object.assign(Object.assign({}, content), { addressingError: getAddressingError(content), categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
343
352
  });
344
353
  }, []);
345
354
  const handleChangeCategories = (0, react_1.useCallback)((value) => {
@@ -368,7 +377,8 @@ function Composer(inProps) {
368
377
  else if (event || (value && Object.prototype.hasOwnProperty.call(value, 'recurring'))) {
369
378
  dispatch({ type: 'event', value });
370
379
  }
371
- else if ((recipients === null || recipients === void 0 ? void 0 : recipients.length) !== 0 || (value && Array.isArray(value) && value.some((obj) => !('color' in obj)))) {
380
+ else if ((recipients === null || recipients === void 0 ? void 0 : recipients.length) > 0 ||
381
+ (Array.isArray(value) && value.some((item) => typeof item === 'object' && item !== null && !('color' in item)))) {
372
382
  dispatch({
373
383
  type: 'multiple',
374
384
  value: {
@@ -399,7 +409,7 @@ function Composer(inProps) {
399
409
  ? group
400
410
  : event || (addressing && Object.prototype.hasOwnProperty.call(addressing, 'recurring'))
401
411
  ? event
402
- : (recipients === null || recipients === void 0 ? void 0 : recipients.length) && !recipients.some((r) => 'color' in r)
412
+ : (recipients === null || recipients === void 0 ? void 0 : recipients.length) !== 0 || ((recipients === null || recipients === void 0 ? void 0 : recipients.length) !== 0 && !recipients.some((r) => 'color' in r))
403
413
  ? recipients
404
414
  : addressing
405
415
  }
@@ -464,8 +474,7 @@ function Composer(inProps) {
464
474
  const handleChangeAttributes = (0, react_1.useCallback)((content) => {
465
475
  dispatch({
466
476
  type: 'multiple',
467
- value: Object.assign(Object.assign({}, content), { addressingError: addressingRequiredEnabled &&
468
- (!content.addressing || content.addressing.length === 0 || !content.recipients || content.recipients.length === 0) ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" })) : null, categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
477
+ value: Object.assign(Object.assign({}, content), { addressingError: getAddressingError(content), categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
469
478
  });
470
479
  }, []);
471
480
  const handleClickAttributes = (0, react_1.useCallback)((attr) => {
@@ -476,6 +485,9 @@ function Composer(inProps) {
476
485
  case 'addressing':
477
486
  handleAddAudienceLayer();
478
487
  break;
488
+ case 'recipients':
489
+ handleAddAudienceLayer();
490
+ break;
479
491
  case 'location':
480
492
  handleAddLocationLayer();
481
493
  break;
@@ -83,7 +83,12 @@ const AudienceLayer = react_1.default.forwardRef((props, ref) => {
83
83
  ? AudienceTypes.AUDIENCE_EVENT
84
84
  : Object.prototype.hasOwnProperty.call(defaultValue, 'managed_by')
85
85
  ? AudienceTypes.AUDIENCE_GROUP
86
- : Array.isArray(defaultValue) && defaultValue.length && ((_a = defaultValue[0]) === null || _a === void 0 ? void 0 : _a.username)
86
+ : Array.isArray(defaultValue) &&
87
+ defaultValue.length > 0 &&
88
+ // case: array of user objects
89
+ (((_a = defaultValue[0]) === null || _a === void 0 ? void 0 : _a.username) !== undefined ||
90
+ // case: array of strings
91
+ typeof defaultValue[0] === 'string')
87
92
  ? AudienceTypes.AUDIENCE_USERS
88
93
  : AudienceTypes.AUDIENCE_TAG);
89
94
  // HANDLERS
@@ -107,11 +112,19 @@ const AudienceLayer = react_1.default.forwardRef((props, ref) => {
107
112
  (Boolean((value === null || value === void 0 ? void 0 : value.length) === 0) && audience === AudienceTypes.AUDIENCE_ALL && Boolean((defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.length) !== 0)), value: AudienceTypes.AUDIENCE_EVENT, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "CalendarIcon" }), label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.event", defaultMessage: "ui.composer.layer.audience.event" }) })), groupsEnabled && ((0, jsx_runtime_1.jsx)(material_1.Tab, { disabled: (Boolean(value === null || value === void 0 ? void 0 : value.length) && !Object.prototype.hasOwnProperty.call(value, 'managed_by')) ||
108
113
  (value !== undefined && Boolean(!(value === null || value === void 0 ? void 0 : value.length)) && audience !== AudienceTypes.AUDIENCE_ALL) ||
109
114
  (Boolean((value === null || value === void 0 ? void 0 : value.length) === 0) && audience === AudienceTypes.AUDIENCE_ALL && Boolean((defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.length) !== 0)), value: AudienceTypes.AUDIENCE_GROUP, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "groups" }), label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.group", defaultMessage: "ui.composer.layer.audience.group" }) })), (0, jsx_runtime_1.jsx)(material_1.Tab, { disabled: value &&
110
- ((Array.isArray(value) && value.some((v) => v === null || v === void 0 ? void 0 : v.username)) ||
111
- (!Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, 'managed_by'))), value: AudienceTypes.AUDIENCE_TAG, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "label" }), label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.tag", defaultMessage: "ui.composer.layer.audience.tag" }) }), usersTaggingEnabled && ((0, jsx_runtime_1.jsx)(material_1.Tab, { disabled: value &&
112
- ((Array.isArray(value) && value.length && !value.some((v) => v === null || v === void 0 ? void 0 : v.username)) ||
113
- (!Array.isArray(value) && Object.keys(value).length && Object.prototype.hasOwnProperty.call(value, 'managed_by')) ||
114
- (!Array.isArray(value) && Object.keys(value).length && Object.prototype.hasOwnProperty.call(value, 'recurring'))), value: AudienceTypes.AUDIENCE_USERS, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "people_alt" }), label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.users", defaultMessage: "ui.composer.layer.audience.users" }) }))] })), (0, jsx_runtime_1.jsxs)(material_1.Typography, Object.assign({ className: classes.message }, { children: [audience === AudienceTypes.AUDIENCE_ALL && !taggingRequiredEnabled && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.all.message", defaultMessage: "ui.composer.layer.audience.all.message" })), audience === AudienceTypes.AUDIENCE_EVENT && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.event.message", defaultMessage: "ui.composer.layer.audience.event.message" })), audience === AudienceTypes.AUDIENCE_GROUP && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.group.message", defaultMessage: "ui.composer.layer.audience.group.message" })), audience === AudienceTypes.AUDIENCE_TAG && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.tag.message", defaultMessage: "ui.composer.layer.audience.tag.message" })), audience === AudienceTypes.AUDIENCE_USERS && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.users.message", defaultMessage: "ui.composer.layer.audience.users.message" }))] })), audience === AudienceTypes.AUDIENCE_TAG && ((0, jsx_runtime_1.jsx)(material_1.Autocomplete, { className: classes.autocomplete, open: autocompleteOpen, onOpen: handleAutocompleteOpen, onClose: handleAutocompleteClose, multiple: true, options: scAddressingTags || [], getOptionLabel: (option) => option.name || '', value: value, selectOnFocus: true, clearOnBlur: true, handleHomeEndKeys: true, clearIcon: null, noOptionsText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.tags.empty", defaultMessage: "ui.composer.layer.audience.tags.empty" }), onChange: handleChange, isOptionEqualToValue: (option, value) => value.id === option.id, renderTags: (value, getTagProps) => {
115
+ ((Array.isArray(value) &&
116
+ (value.some((v) => v === null || v === void 0 ? void 0 : v.username) || // user tagging
117
+ value.some((v) => typeof v === 'string'))) ||
118
+ (!Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, 'managed_by'))) // group object
119
+ , value: AudienceTypes.AUDIENCE_TAG, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "label" }), label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.tag", defaultMessage: "ui.composer.layer.audience.tag" }) }), usersTaggingEnabled && ((0, jsx_runtime_1.jsx)(material_1.Tab, { disabled: value &&
120
+ ((Array.isArray(value) &&
121
+ value.length > 0 &&
122
+ // disable only if NOT user objects and NOT strings
123
+ !value.some((v) => v === null || v === void 0 ? void 0 : v.username) &&
124
+ !value.every((v) => typeof v === 'string')) ||
125
+ (!Array.isArray(value) &&
126
+ Object.keys(value).length > 0 &&
127
+ (Object.prototype.hasOwnProperty.call(value, 'managed_by') || Object.prototype.hasOwnProperty.call(value, 'recurring')))), value: AudienceTypes.AUDIENCE_USERS, icon: (0, jsx_runtime_1.jsx)(material_1.Icon, { children: "people_alt" }), label: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.users", defaultMessage: "ui.composer.layer.audience.users" }) }))] })), (0, jsx_runtime_1.jsxs)(material_1.Typography, Object.assign({ className: classes.message }, { children: [audience === AudienceTypes.AUDIENCE_ALL && !taggingRequiredEnabled && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.all.message", defaultMessage: "ui.composer.layer.audience.all.message" })), audience === AudienceTypes.AUDIENCE_EVENT && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.event.message", defaultMessage: "ui.composer.layer.audience.event.message" })), audience === AudienceTypes.AUDIENCE_GROUP && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.group.message", defaultMessage: "ui.composer.layer.audience.group.message" })), audience === AudienceTypes.AUDIENCE_TAG && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.tag.message", defaultMessage: "ui.composer.layer.audience.tag.message" })), audience === AudienceTypes.AUDIENCE_USERS && ((0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.users.message", defaultMessage: "ui.composer.layer.audience.users.message" }))] })), audience === AudienceTypes.AUDIENCE_TAG && ((0, jsx_runtime_1.jsx)(material_1.Autocomplete, { className: classes.autocomplete, open: autocompleteOpen, onOpen: handleAutocompleteOpen, onClose: handleAutocompleteClose, multiple: true, options: scAddressingTags || [], getOptionLabel: (option) => option.name || '', value: value, selectOnFocus: true, clearOnBlur: true, handleHomeEndKeys: true, clearIcon: null, noOptionsText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.tags.empty", defaultMessage: "ui.composer.layer.audience.tags.empty" }), onChange: handleChange, isOptionEqualToValue: (option, value) => value.id === option.id, renderTags: (value, getTagProps) => {
115
128
  return value.map((option, index) => (0, jsx_runtime_1.jsx)(TagChip_1.default, Object.assign({ tag: option }, getTagProps({ index })), option.id));
116
129
  }, renderOption: (props, option, { selected, inputValue }) => {
117
130
  const matches = (0, match_1.default)(option.name, inputValue);
@@ -24,9 +24,9 @@ const Root = (0, material_1.styled)(BaseDialog_1.default, {
24
24
  const Transition = react_1.default.forwardRef(function Transition(props, ref) {
25
25
  return (0, jsx_runtime_1.jsx)(material_1.Slide, Object.assign({ direction: "up", ref: ref }, props));
26
26
  });
27
- const NoTransition = react_1.default.forwardRef(function NoTransition(props) {
28
- return (0, jsx_runtime_1.jsxs)(react_1.default.Fragment, { children: [" ", props.children, " "] });
29
- });
27
+ const NoTransition = function NoTransition(props) {
28
+ return (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: props.children });
29
+ };
30
30
  function PdfPreviewDialog(inProps) {
31
31
  // PROPS
32
32
  const props = (0, system_1.useThemeProps)({
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = tslib_1.__importStar(require("react"));
5
+ const react_1 = require("react");
6
6
  const react_intl_1 = require("react-intl");
7
7
  const parse_1 = tslib_1.__importDefault(require("autosuggest-highlight/parse"));
8
8
  const match_1 = tslib_1.__importDefault(require("autosuggest-highlight/match"));
@@ -36,27 +36,42 @@ const UserAutocomplete = (inProps) => {
36
36
  } } = props, rest = tslib_1.__rest(props, ["onChange", "defaultValue", "disabled", "TextFieldProps"]);
37
37
  // State
38
38
  const [open, setOpen] = (0, react_1.useState)(false);
39
- // const [value, setValue] = useState<string | SCUserAutocompleteType | (string | SCUserAutocompleteType)[]>(
40
- // typeof defaultValue === 'string' ? null : defaultValue
41
- // );
42
- const [value, setValue] = (0, react_1.useState)(Array.isArray(defaultValue) ? defaultValue : defaultValue ? [defaultValue] : []);
39
+ const [inputValue, setInputValue] = (0, react_1.useState)('');
40
+ const [usersMap, setUsersMap] = (0, react_1.useState)({});
41
+ const [value, setValue] = (0, react_1.useState)([]);
43
42
  const [textAreaValue, setTextAreaValue] = (0, react_1.useState)('');
44
43
  // Fetch users
45
44
  const { users, isLoading } = (0, react_core_1.useSCFetchUsers)();
45
+ // Build map for quick lookup by username
46
46
  (0, react_1.useEffect)(() => {
47
- if (value === null) {
47
+ const map = {};
48
+ users === null || users === void 0 ? void 0 : users.forEach((u) => {
49
+ map[u.username] = u;
50
+ });
51
+ setUsersMap(map);
52
+ }, [users]);
53
+ // Initialize value from defaultValue (string or object)
54
+ (0, react_1.useEffect)(() => {
55
+ if (!defaultValue)
48
56
  return;
49
- }
57
+ const initial = (Array.isArray(defaultValue) ? defaultValue : [defaultValue]).map((v) => {
58
+ if (typeof v === 'string') {
59
+ // Use fetched user if available, otherwise fallback object
60
+ return usersMap[v] || { id: `fallback-${v}`, username: v, avatar: '' };
61
+ }
62
+ return v;
63
+ });
64
+ setValue(initial);
65
+ setTextAreaValue(initial.map((u) => u.username).join('\n'));
66
+ }, [defaultValue, usersMap]);
67
+ // Trigger onChange and sync textarea
68
+ (0, react_1.useEffect)(() => {
50
69
  onChange === null || onChange === void 0 ? void 0 : onChange(value);
51
70
  setTextAreaValue(value.map((u) => u.username).join('\n'));
52
71
  }, [value]);
53
72
  // Handlers
54
- const handleOpen = () => {
55
- setOpen(true);
56
- };
57
- const handleClose = () => {
58
- setOpen(false);
59
- };
73
+ const handleOpen = () => setOpen(true);
74
+ const handleClose = () => setOpen(false);
60
75
  const handleChange = (_event, newValue) => {
61
76
  setValue(newValue);
62
77
  };
@@ -65,14 +80,13 @@ const UserAutocomplete = (inProps) => {
65
80
  .split(/\s|,|\n/)
66
81
  .map((s) => s.trim())
67
82
  .filter(Boolean);
68
- const matched = users.filter((u) => names.includes(u.username));
83
+ const matched = names.map((n) => usersMap[n] || { id: `fallback-${n}`, username: n, avatar: '' });
69
84
  setValue(matched);
70
85
  setTextAreaValue(e.target.value);
71
86
  };
72
- return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [(0, jsx_runtime_1.jsx)(AutocompleteRoot, Object.assign({ multiple: true, className: classes.autocompleteRoot, open: open, onOpen: handleOpen, onClose: handleClose, options: users || [], getOptionLabel: (option) => option.username || '', value: value, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.userAutocomplete.empty", defaultMessage: "ui.userAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, val) => val.id === option.id, renderTags: (value, getTagProps) => value.map((option, index) => ((0, jsx_runtime_1.jsx)(material_1.Chip, Object.assign({ avatar: (0, jsx_runtime_1.jsx)(material_1.Avatar, { src: option.avatar }), label: option.username }, getTagProps({ index })), option.id))), renderOption: (props, option, { inputValue }) => {
73
- const matches = (0, match_1.default)(option.username, inputValue);
74
- const parts = (0, parse_1.default)(option.username, matches);
75
- return ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ component: "li" }, props, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: option.username, src: option.avatar, sx: { marginRight: 1 } }), (0, jsx_runtime_1.jsx)(react_1.default.Fragment, { children: parts.map((part, index) => ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ sx: { fontWeight: part.highlight ? 700 : 400 } }, { children: part.text }), index))) })] })));
87
+ return ((0, jsx_runtime_1.jsxs)(Root, Object.assign({ className: classes.root }, { children: [(0, jsx_runtime_1.jsx)(AutocompleteRoot, Object.assign({ multiple: true, className: classes.autocompleteRoot, open: open, onOpen: handleOpen, onClose: handleClose, options: users || [], getOptionLabel: (option) => option.username || '', value: value, inputValue: inputValue, onInputChange: (_e, newInput) => setInputValue(newInput), selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.userAutocomplete.empty", defaultMessage: "ui.userAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, val) => option.id === val.id, renderTags: (value, getTagProps) => value.map((option, index) => ((0, jsx_runtime_1.jsx)(material_1.Chip, Object.assign({ avatar: (0, jsx_runtime_1.jsx)(material_1.Avatar, { src: option.avatar }), label: option.username }, getTagProps({ index })), option.id))), renderOption: (props, option, { inputValue }) => {
88
+ const parts = (0, parse_1.default)(option.username, (0, match_1.default)(option.username, inputValue));
89
+ return ((0, jsx_runtime_1.jsxs)(material_1.Box, Object.assign({ component: "li" }, props, { children: [(0, jsx_runtime_1.jsx)(material_1.Avatar, { alt: option.username, src: option.avatar, sx: { mr: 1 } }), parts.map((part, index) => ((0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ sx: { fontWeight: part.highlight ? 700 : 400 } }, { children: part.text }), index)))] })));
76
90
  }, renderInput: (params) => ((0, jsx_runtime_1.jsx)(material_1.TextField, Object.assign({}, params, TextFieldProps, { margin: "dense", InputProps: Object.assign(Object.assign({}, params.InputProps), { autoComplete: 'off', endAdornment: ((0, jsx_runtime_1.jsxs)(react_1.Fragment, { children: [isLoading ? (0, jsx_runtime_1.jsx)(material_1.CircularProgress, { color: "inherit", size: 20 }) : null, params.InputProps.endAdornment] })) }) }))) }, rest)), (0, jsx_runtime_1.jsx)(material_1.Typography, Object.assign({ variant: "body2", color: "primary", className: classes.info }, { children: (0, jsx_runtime_1.jsx)(react_intl_1.FormattedMessage, { id: "ui.userAutocomplete.textarea.info", defaultMessage: "ui.userAutocomplete.textarea.info", values: {
77
91
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
78
92
  // @ts-ignore
@@ -12,7 +12,7 @@ const Root = styled(Box, {
12
12
  slot: 'AttributesRoot'
13
13
  })(() => ({}));
14
14
  export default (props) => {
15
- var _a, _b, _c, _d;
15
+ var _a, _b, _c, _d, _e;
16
16
  // PROPS
17
17
  const { className = null, value = null, onChange = null, onClick = null } = props;
18
18
  // HANDLERS
@@ -46,13 +46,16 @@ export default (props) => {
46
46
  const handleClickLocation = useCallback(() => {
47
47
  onClick && onClick('location');
48
48
  }, [onClick]);
49
- const handleDeleteRecipient = useCallback((id) => () => {
50
- onChange && onChange(Object.assign(Object.assign({}, value), { recipients: value.recipients.filter((r) => r.id !== id) }));
49
+ const handleDeleteRecipient = useCallback((identifier) => () => {
50
+ if (!(value === null || value === void 0 ? void 0 : value.recipients))
51
+ return;
52
+ onChange &&
53
+ onChange(Object.assign(Object.assign({}, value), { recipients: value.recipients.filter((r) => typeof r === 'object' ? r.id !== identifier : r !== identifier) }));
51
54
  }, [value, onChange]);
52
55
  const handleClickRecipient = useCallback(() => {
53
56
  onClick && onClick('recipients');
54
57
  }, [onClick]);
55
58
  return (_jsxs(Root, Object.assign({ className: classNames(classes.root, className) }, { children: [((_a = value === null || value === void 0 ? void 0 : value.categories) === null || _a === void 0 ? void 0 : _a.length) > 0 &&
56
59
  (value === null || value === void 0 ? void 0 : value.categories.map((c) => (_jsx(Chip, { label: c.name, onDelete: handleDeleteCategory(c.id), icon: _jsx(Icon, { children: "category" }), onClick: handleClickCategory }, c.id)))), (value === null || value === void 0 ? void 0 : value.group) && (_jsx(Chip, { label: value === null || value === void 0 ? void 0 : value.group.name, onDelete: handleDeleteGroup, icon: _jsx(Icon, { children: "groups" }), onClick: handleClickGroup, disabled: !((_b = value === null || value === void 0 ? void 0 : value.group) === null || _b === void 0 ? void 0 : _b.subscription_status) }, value === null || value === void 0 ? void 0 : value.group.id)), (value === null || value === void 0 ? void 0 : value.event) && (_jsx(Chip, { label: value === null || value === void 0 ? void 0 : value.event.name, onDelete: handleDeleteEvent, icon: _jsx(Icon, { children: "CalendarIcon" }), onClick: handleClickEvent, disabled: !((_c = value === null || value === void 0 ? void 0 : value.event) === null || _c === void 0 ? void 0 : _c.subscription_status) }, value === null || value === void 0 ? void 0 : value.event.id)), ((_d = value === null || value === void 0 ? void 0 : value.addressing) === null || _d === void 0 ? void 0 : _d.length) > 0 &&
57
- (value === null || value === void 0 ? void 0 : value.addressing.map((t) => (_jsx(TagChip, { tag: t, onDelete: handleDeleteTag(t.id), icon: _jsx(Icon, { children: "label" }), onClick: handleClickTag }, t.id)))), _jsx(_Fragment, { children: (value === null || value === void 0 ? void 0 : value.recipients.length) > 0 && (_jsxs(_Fragment, { children: [value.recipients.slice(0, 3).map((r) => (_jsx(Chip, { label: r.username, icon: _jsx(Icon, { children: "people_alt" }), onClick: handleClickRecipient, onDelete: handleDeleteRecipient(r.id) }, r.id))), value.recipients.length > 3 && _jsx(Chip, { label: `+${value.recipients.length - 3}` })] })) }), (value === null || value === void 0 ? void 0 : value.location) && (_jsx(Chip, { icon: _jsx(Icon, { children: "add_location_alt" }), label: value === null || value === void 0 ? void 0 : value.location.location, onDelete: handleDeleteLocation, onClick: handleClickLocation }))] })));
60
+ (value === null || value === void 0 ? void 0 : value.addressing.map((t) => (_jsx(TagChip, { tag: t, onDelete: handleDeleteTag(t.id), icon: _jsx(Icon, { children: "label" }), onClick: handleClickTag }, t.id)))), _jsx(_Fragment, { children: ((_e = value === null || value === void 0 ? void 0 : value.recipients) === null || _e === void 0 ? void 0 : _e.length) > 0 && (_jsxs(_Fragment, { children: [value.recipients.slice(0, 3).map((r) => (_jsx(Chip, { label: typeof r === 'object' ? r.username : r, icon: _jsx(Icon, { children: "people_alt" }), onClick: handleClickRecipient, onDelete: handleDeleteRecipient(typeof r === 'object' ? r.id : r) }, typeof r === 'object' ? r.id : r))), value.recipients.length > 3 && _jsx(Chip, { label: `+${value.recipients.length - 3}` })] })) }), (value === null || value === void 0 ? void 0 : value.location) && (_jsx(Chip, { icon: _jsx(Icon, { children: "add_location_alt" }), label: value === null || value === void 0 ? void 0 : value.location.location, onDelete: handleDeleteLocation, onClick: handleClickLocation }))] })));
58
61
  };
@@ -157,6 +157,11 @@ export default function Composer(inProps) {
157
157
  const categoryRequiredEnabled = useMemo(() => preferences &&
158
158
  SCPreferences.CONFIGURATIONS_POST_CATEGORY_REQUIRED_ENABLED in preferences &&
159
159
  preferences[SCPreferences.CONFIGURATIONS_POST_CATEGORY_REQUIRED_ENABLED].value, [preferences]);
160
+ const usersTaggingEnabled = useMemo(() => preferences &&
161
+ features &&
162
+ features.includes(SCFeatureName.TAGGING) &&
163
+ SCPreferences.CONFIGURATIONS_POST_USER_ADDRESSING_ENABLED in preferences &&
164
+ preferences[SCPreferences.CONFIGURATIONS_POST_USER_ADDRESSING_ENABLED].value, [preferences, features]);
160
165
  const destructureFeedObject = (_feedObject) => {
161
166
  if (_feedObject.type === SCContributionType.POST) {
162
167
  _feedObject = _feedObject;
@@ -317,27 +322,31 @@ export default function Composer(inProps) {
317
322
  const handleChangeType = useCallback((value) => {
318
323
  dispatch({ type: 'type', value });
319
324
  }, []);
325
+ const getAddressingError = (content) => {
326
+ var _a, _b;
327
+ const isMissing = addressingRequiredEnabled && !((_a = content.addressing) === null || _a === void 0 ? void 0 : _a.length) && !((_b = content.recipients) === null || _b === void 0 ? void 0 : _b.length);
328
+ if (!isMissing)
329
+ return null;
330
+ return usersTaggingEnabled ? (_jsx(FormattedMessage, { id: "ui.composer.addressingRecipients.error.missing", defaultMessage: "ui.composer.addressingRecipients.error.missing" })) : (_jsx(FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" }));
331
+ };
320
332
  const handleChangePoll = useCallback((content) => {
321
333
  dispatch({
322
334
  type: 'multiple',
323
335
  value: Object.assign(Object.assign({}, content), { pollError: content.poll.title.length > COMPOSER_TITLE_MAX_LENGTH
324
336
  ? { titleError: _jsx(FormattedMessage, { id: "ui.composer.title.error.maxlength", defaultMessage: "ui.composer.title.error.maxlength" }) }
325
- : null, addressingError: addressingRequiredEnabled &&
326
- (!content.addressing || content.addressing.length === 0 || !content.recipients || content.recipients.length === 0) ? (_jsx(FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" })) : null })
337
+ : null, addressingError: getAddressingError(content) })
327
338
  });
328
339
  }, []);
329
340
  const handleChangeDiscussion = useCallback((content) => {
330
341
  dispatch({
331
342
  type: 'multiple',
332
- value: Object.assign(Object.assign({}, content), { titleError: content.title.length > COMPOSER_TITLE_MAX_LENGTH ? (_jsx(FormattedMessage, { id: "ui.composer.title.error.maxlength", defaultMessage: "ui.composer.title.error.maxlength" })) : null, addressingError: addressingRequiredEnabled &&
333
- (!content.addressing || content.addressing.length === 0 || !content.recipients || content.recipients.length === 0) ? (_jsx(FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" })) : null, categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? (_jsx(FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
343
+ value: Object.assign(Object.assign({}, content), { titleError: content.title.length > COMPOSER_TITLE_MAX_LENGTH ? (_jsx(FormattedMessage, { id: "ui.composer.title.error.maxlength", defaultMessage: "ui.composer.title.error.maxlength" })) : null, addressingError: getAddressingError(content), categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? (_jsx(FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
334
344
  });
335
345
  }, []);
336
346
  const handleChangePost = useCallback((content) => {
337
347
  dispatch({
338
348
  type: 'multiple',
339
- value: Object.assign(Object.assign({}, content), { addressingError: addressingRequiredEnabled &&
340
- (!content.addressing || content.addressing.length === 0 || !content.recipients || content.recipients.length === 0) ? (_jsx(FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" })) : null, categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? (_jsx(FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
349
+ value: Object.assign(Object.assign({}, content), { addressingError: getAddressingError(content), categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? (_jsx(FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
341
350
  });
342
351
  }, []);
343
352
  const handleChangeCategories = useCallback((value) => {
@@ -366,7 +375,8 @@ export default function Composer(inProps) {
366
375
  else if (event || (value && Object.prototype.hasOwnProperty.call(value, 'recurring'))) {
367
376
  dispatch({ type: 'event', value });
368
377
  }
369
- else if ((recipients === null || recipients === void 0 ? void 0 : recipients.length) !== 0 || (value && Array.isArray(value) && value.some((obj) => !('color' in obj)))) {
378
+ else if ((recipients === null || recipients === void 0 ? void 0 : recipients.length) > 0 ||
379
+ (Array.isArray(value) && value.some((item) => typeof item === 'object' && item !== null && !('color' in item)))) {
370
380
  dispatch({
371
381
  type: 'multiple',
372
382
  value: {
@@ -397,7 +407,7 @@ export default function Composer(inProps) {
397
407
  ? group
398
408
  : event || (addressing && Object.prototype.hasOwnProperty.call(addressing, 'recurring'))
399
409
  ? event
400
- : (recipients === null || recipients === void 0 ? void 0 : recipients.length) && !recipients.some((r) => 'color' in r)
410
+ : (recipients === null || recipients === void 0 ? void 0 : recipients.length) !== 0 || ((recipients === null || recipients === void 0 ? void 0 : recipients.length) !== 0 && !recipients.some((r) => 'color' in r))
401
411
  ? recipients
402
412
  : addressing
403
413
  }
@@ -462,8 +472,7 @@ export default function Composer(inProps) {
462
472
  const handleChangeAttributes = useCallback((content) => {
463
473
  dispatch({
464
474
  type: 'multiple',
465
- value: Object.assign(Object.assign({}, content), { addressingError: addressingRequiredEnabled &&
466
- (!content.addressing || content.addressing.length === 0 || !content.recipients || content.recipients.length === 0) ? (_jsx(FormattedMessage, { id: "ui.composer.addressing.error.missing", defaultMessage: "ui.composer.addressing.error.missing" })) : null, categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? (_jsx(FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
475
+ value: Object.assign(Object.assign({}, content), { addressingError: getAddressingError(content), categoriesError: categoryRequiredEnabled && content.categories.length === 0 ? (_jsx(FormattedMessage, { id: "ui.composer.categories.error.missing", defaultMessage: "ui.composer.categories.error.missing" })) : null })
467
476
  });
468
477
  }, []);
469
478
  const handleClickAttributes = useCallback((attr) => {
@@ -474,6 +483,9 @@ export default function Composer(inProps) {
474
483
  case 'addressing':
475
484
  handleAddAudienceLayer();
476
485
  break;
486
+ case 'recipients':
487
+ handleAddAudienceLayer();
488
+ break;
477
489
  case 'location':
478
490
  handleAddLocationLayer();
479
491
  break;
@@ -80,7 +80,12 @@ const AudienceLayer = React.forwardRef((props, ref) => {
80
80
  ? AudienceTypes.AUDIENCE_EVENT
81
81
  : Object.prototype.hasOwnProperty.call(defaultValue, 'managed_by')
82
82
  ? AudienceTypes.AUDIENCE_GROUP
83
- : Array.isArray(defaultValue) && defaultValue.length && ((_a = defaultValue[0]) === null || _a === void 0 ? void 0 : _a.username)
83
+ : Array.isArray(defaultValue) &&
84
+ defaultValue.length > 0 &&
85
+ // case: array of user objects
86
+ (((_a = defaultValue[0]) === null || _a === void 0 ? void 0 : _a.username) !== undefined ||
87
+ // case: array of strings
88
+ typeof defaultValue[0] === 'string')
84
89
  ? AudienceTypes.AUDIENCE_USERS
85
90
  : AudienceTypes.AUDIENCE_TAG);
86
91
  // HANDLERS
@@ -104,11 +109,19 @@ const AudienceLayer = React.forwardRef((props, ref) => {
104
109
  (Boolean((value === null || value === void 0 ? void 0 : value.length) === 0) && audience === AudienceTypes.AUDIENCE_ALL && Boolean((defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.length) !== 0)), value: AudienceTypes.AUDIENCE_EVENT, icon: _jsx(Icon, { children: "CalendarIcon" }), label: _jsx(FormattedMessage, { id: "ui.composer.layer.audience.event", defaultMessage: "ui.composer.layer.audience.event" }) })), groupsEnabled && (_jsx(Tab, { disabled: (Boolean(value === null || value === void 0 ? void 0 : value.length) && !Object.prototype.hasOwnProperty.call(value, 'managed_by')) ||
105
110
  (value !== undefined && Boolean(!(value === null || value === void 0 ? void 0 : value.length)) && audience !== AudienceTypes.AUDIENCE_ALL) ||
106
111
  (Boolean((value === null || value === void 0 ? void 0 : value.length) === 0) && audience === AudienceTypes.AUDIENCE_ALL && Boolean((defaultValue === null || defaultValue === void 0 ? void 0 : defaultValue.length) !== 0)), value: AudienceTypes.AUDIENCE_GROUP, icon: _jsx(Icon, { children: "groups" }), label: _jsx(FormattedMessage, { id: "ui.composer.layer.audience.group", defaultMessage: "ui.composer.layer.audience.group" }) })), _jsx(Tab, { disabled: value &&
107
- ((Array.isArray(value) && value.some((v) => v === null || v === void 0 ? void 0 : v.username)) ||
108
- (!Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, 'managed_by'))), value: AudienceTypes.AUDIENCE_TAG, icon: _jsx(Icon, { children: "label" }), label: _jsx(FormattedMessage, { id: "ui.composer.layer.audience.tag", defaultMessage: "ui.composer.layer.audience.tag" }) }), usersTaggingEnabled && (_jsx(Tab, { disabled: value &&
109
- ((Array.isArray(value) && value.length && !value.some((v) => v === null || v === void 0 ? void 0 : v.username)) ||
110
- (!Array.isArray(value) && Object.keys(value).length && Object.prototype.hasOwnProperty.call(value, 'managed_by')) ||
111
- (!Array.isArray(value) && Object.keys(value).length && Object.prototype.hasOwnProperty.call(value, 'recurring'))), value: AudienceTypes.AUDIENCE_USERS, icon: _jsx(Icon, { children: "people_alt" }), label: _jsx(FormattedMessage, { id: "ui.composer.layer.audience.users", defaultMessage: "ui.composer.layer.audience.users" }) }))] })), _jsxs(Typography, Object.assign({ className: classes.message }, { children: [audience === AudienceTypes.AUDIENCE_ALL && !taggingRequiredEnabled && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.all.message", defaultMessage: "ui.composer.layer.audience.all.message" })), audience === AudienceTypes.AUDIENCE_EVENT && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.event.message", defaultMessage: "ui.composer.layer.audience.event.message" })), audience === AudienceTypes.AUDIENCE_GROUP && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.group.message", defaultMessage: "ui.composer.layer.audience.group.message" })), audience === AudienceTypes.AUDIENCE_TAG && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.tag.message", defaultMessage: "ui.composer.layer.audience.tag.message" })), audience === AudienceTypes.AUDIENCE_USERS && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.users.message", defaultMessage: "ui.composer.layer.audience.users.message" }))] })), audience === AudienceTypes.AUDIENCE_TAG && (_jsx(Autocomplete, { className: classes.autocomplete, open: autocompleteOpen, onOpen: handleAutocompleteOpen, onClose: handleAutocompleteClose, multiple: true, options: scAddressingTags || [], getOptionLabel: (option) => option.name || '', value: value, selectOnFocus: true, clearOnBlur: true, handleHomeEndKeys: true, clearIcon: null, noOptionsText: _jsx(FormattedMessage, { id: "ui.composer.layer.audience.tags.empty", defaultMessage: "ui.composer.layer.audience.tags.empty" }), onChange: handleChange, isOptionEqualToValue: (option, value) => value.id === option.id, renderTags: (value, getTagProps) => {
112
+ ((Array.isArray(value) &&
113
+ (value.some((v) => v === null || v === void 0 ? void 0 : v.username) || // user tagging
114
+ value.some((v) => typeof v === 'string'))) ||
115
+ (!Array.isArray(value) && Object.prototype.hasOwnProperty.call(value, 'managed_by'))) // group object
116
+ , value: AudienceTypes.AUDIENCE_TAG, icon: _jsx(Icon, { children: "label" }), label: _jsx(FormattedMessage, { id: "ui.composer.layer.audience.tag", defaultMessage: "ui.composer.layer.audience.tag" }) }), usersTaggingEnabled && (_jsx(Tab, { disabled: value &&
117
+ ((Array.isArray(value) &&
118
+ value.length > 0 &&
119
+ // disable only if NOT user objects and NOT strings
120
+ !value.some((v) => v === null || v === void 0 ? void 0 : v.username) &&
121
+ !value.every((v) => typeof v === 'string')) ||
122
+ (!Array.isArray(value) &&
123
+ Object.keys(value).length > 0 &&
124
+ (Object.prototype.hasOwnProperty.call(value, 'managed_by') || Object.prototype.hasOwnProperty.call(value, 'recurring')))), value: AudienceTypes.AUDIENCE_USERS, icon: _jsx(Icon, { children: "people_alt" }), label: _jsx(FormattedMessage, { id: "ui.composer.layer.audience.users", defaultMessage: "ui.composer.layer.audience.users" }) }))] })), _jsxs(Typography, Object.assign({ className: classes.message }, { children: [audience === AudienceTypes.AUDIENCE_ALL && !taggingRequiredEnabled && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.all.message", defaultMessage: "ui.composer.layer.audience.all.message" })), audience === AudienceTypes.AUDIENCE_EVENT && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.event.message", defaultMessage: "ui.composer.layer.audience.event.message" })), audience === AudienceTypes.AUDIENCE_GROUP && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.group.message", defaultMessage: "ui.composer.layer.audience.group.message" })), audience === AudienceTypes.AUDIENCE_TAG && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.tag.message", defaultMessage: "ui.composer.layer.audience.tag.message" })), audience === AudienceTypes.AUDIENCE_USERS && (_jsx(FormattedMessage, { id: "ui.composer.layer.audience.users.message", defaultMessage: "ui.composer.layer.audience.users.message" }))] })), audience === AudienceTypes.AUDIENCE_TAG && (_jsx(Autocomplete, { className: classes.autocomplete, open: autocompleteOpen, onOpen: handleAutocompleteOpen, onClose: handleAutocompleteClose, multiple: true, options: scAddressingTags || [], getOptionLabel: (option) => option.name || '', value: value, selectOnFocus: true, clearOnBlur: true, handleHomeEndKeys: true, clearIcon: null, noOptionsText: _jsx(FormattedMessage, { id: "ui.composer.layer.audience.tags.empty", defaultMessage: "ui.composer.layer.audience.tags.empty" }), onChange: handleChange, isOptionEqualToValue: (option, value) => value.id === option.id, renderTags: (value, getTagProps) => {
112
125
  return value.map((option, index) => _jsx(TagChip, Object.assign({ tag: option }, getTagProps({ index })), option.id));
113
126
  }, renderOption: (props, option, { selected, inputValue }) => {
114
127
  const matches = match(option.name, inputValue);
@@ -22,9 +22,9 @@ const Root = styled(BaseDialog, {
22
22
  const Transition = React.forwardRef(function Transition(props, ref) {
23
23
  return _jsx(Slide, Object.assign({ direction: "up", ref: ref }, props));
24
24
  });
25
- const NoTransition = React.forwardRef(function NoTransition(props) {
26
- return _jsxs(React.Fragment, { children: [" ", props.children, " "] });
27
- });
25
+ const NoTransition = function NoTransition(props) {
26
+ return _jsx(React.Fragment, { children: props.children });
27
+ };
28
28
  export default function PdfPreviewDialog(inProps) {
29
29
  // PROPS
30
30
  const props = useThemeProps({
@@ -1,6 +1,6 @@
1
1
  import { __rest } from "tslib";
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import React, { Fragment, useEffect, useState } from 'react';
3
+ import { Fragment, useEffect, useState } from 'react';
4
4
  import { FormattedMessage } from 'react-intl';
5
5
  import parse from 'autosuggest-highlight/parse';
6
6
  import match from 'autosuggest-highlight/match';
@@ -34,27 +34,42 @@ const UserAutocomplete = (inProps) => {
34
34
  } } = props, rest = __rest(props, ["onChange", "defaultValue", "disabled", "TextFieldProps"]);
35
35
  // State
36
36
  const [open, setOpen] = useState(false);
37
- // const [value, setValue] = useState<string | SCUserAutocompleteType | (string | SCUserAutocompleteType)[]>(
38
- // typeof defaultValue === 'string' ? null : defaultValue
39
- // );
40
- const [value, setValue] = useState(Array.isArray(defaultValue) ? defaultValue : defaultValue ? [defaultValue] : []);
37
+ const [inputValue, setInputValue] = useState('');
38
+ const [usersMap, setUsersMap] = useState({});
39
+ const [value, setValue] = useState([]);
41
40
  const [textAreaValue, setTextAreaValue] = useState('');
42
41
  // Fetch users
43
42
  const { users, isLoading } = useSCFetchUsers();
43
+ // Build map for quick lookup by username
44
44
  useEffect(() => {
45
- if (value === null) {
45
+ const map = {};
46
+ users === null || users === void 0 ? void 0 : users.forEach((u) => {
47
+ map[u.username] = u;
48
+ });
49
+ setUsersMap(map);
50
+ }, [users]);
51
+ // Initialize value from defaultValue (string or object)
52
+ useEffect(() => {
53
+ if (!defaultValue)
46
54
  return;
47
- }
55
+ const initial = (Array.isArray(defaultValue) ? defaultValue : [defaultValue]).map((v) => {
56
+ if (typeof v === 'string') {
57
+ // Use fetched user if available, otherwise fallback object
58
+ return usersMap[v] || { id: `fallback-${v}`, username: v, avatar: '' };
59
+ }
60
+ return v;
61
+ });
62
+ setValue(initial);
63
+ setTextAreaValue(initial.map((u) => u.username).join('\n'));
64
+ }, [defaultValue, usersMap]);
65
+ // Trigger onChange and sync textarea
66
+ useEffect(() => {
48
67
  onChange === null || onChange === void 0 ? void 0 : onChange(value);
49
68
  setTextAreaValue(value.map((u) => u.username).join('\n'));
50
69
  }, [value]);
51
70
  // Handlers
52
- const handleOpen = () => {
53
- setOpen(true);
54
- };
55
- const handleClose = () => {
56
- setOpen(false);
57
- };
71
+ const handleOpen = () => setOpen(true);
72
+ const handleClose = () => setOpen(false);
58
73
  const handleChange = (_event, newValue) => {
59
74
  setValue(newValue);
60
75
  };
@@ -63,14 +78,13 @@ const UserAutocomplete = (inProps) => {
63
78
  .split(/\s|,|\n/)
64
79
  .map((s) => s.trim())
65
80
  .filter(Boolean);
66
- const matched = users.filter((u) => names.includes(u.username));
81
+ const matched = names.map((n) => usersMap[n] || { id: `fallback-${n}`, username: n, avatar: '' });
67
82
  setValue(matched);
68
83
  setTextAreaValue(e.target.value);
69
84
  };
70
- return (_jsxs(Root, Object.assign({ className: classes.root }, { children: [_jsx(AutocompleteRoot, Object.assign({ multiple: true, className: classes.autocompleteRoot, open: open, onOpen: handleOpen, onClose: handleClose, options: users || [], getOptionLabel: (option) => option.username || '', value: value, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: _jsx(FormattedMessage, { id: "ui.userAutocomplete.empty", defaultMessage: "ui.userAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, val) => val.id === option.id, renderTags: (value, getTagProps) => value.map((option, index) => (_jsx(Chip, Object.assign({ avatar: _jsx(Avatar, { src: option.avatar }), label: option.username }, getTagProps({ index })), option.id))), renderOption: (props, option, { inputValue }) => {
71
- const matches = match(option.username, inputValue);
72
- const parts = parse(option.username, matches);
73
- return (_jsxs(Box, Object.assign({ component: "li" }, props, { children: [_jsx(Avatar, { alt: option.username, src: option.avatar, sx: { marginRight: 1 } }), _jsx(React.Fragment, { children: parts.map((part, index) => (_jsx(Typography, Object.assign({ sx: { fontWeight: part.highlight ? 700 : 400 } }, { children: part.text }), index))) })] })));
85
+ return (_jsxs(Root, Object.assign({ className: classes.root }, { children: [_jsx(AutocompleteRoot, Object.assign({ multiple: true, className: classes.autocompleteRoot, open: open, onOpen: handleOpen, onClose: handleClose, options: users || [], getOptionLabel: (option) => option.username || '', value: value, inputValue: inputValue, onInputChange: (_e, newInput) => setInputValue(newInput), selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: _jsx(FormattedMessage, { id: "ui.userAutocomplete.empty", defaultMessage: "ui.userAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, val) => option.id === val.id, renderTags: (value, getTagProps) => value.map((option, index) => (_jsx(Chip, Object.assign({ avatar: _jsx(Avatar, { src: option.avatar }), label: option.username }, getTagProps({ index })), option.id))), renderOption: (props, option, { inputValue }) => {
86
+ const parts = parse(option.username, match(option.username, inputValue));
87
+ return (_jsxs(Box, Object.assign({ component: "li" }, props, { children: [_jsx(Avatar, { alt: option.username, src: option.avatar, sx: { mr: 1 } }), parts.map((part, index) => (_jsx(Typography, Object.assign({ sx: { fontWeight: part.highlight ? 700 : 400 } }, { children: part.text }), index)))] })));
74
88
  }, renderInput: (params) => (_jsx(TextField, Object.assign({}, params, TextFieldProps, { margin: "dense", InputProps: Object.assign(Object.assign({}, params.InputProps), { autoComplete: 'off', endAdornment: (_jsxs(Fragment, { children: [isLoading ? _jsx(CircularProgress, { color: "inherit", size: 20 }) : null, params.InputProps.endAdornment] })) }) }))) }, rest)), _jsx(Typography, Object.assign({ variant: "body2", color: "primary", className: classes.info }, { children: _jsx(FormattedMessage, { id: "ui.userAutocomplete.textarea.info", defaultMessage: "ui.userAutocomplete.textarea.info", values: {
75
89
  // eslint-disable-next-line @typescript-eslint/ban-ts-ignore
76
90
  // @ts-ignore