@selfcommunity/react-ui 0.7.9-alpha.45 → 0.7.9-alpha.47
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.
- package/lib/cjs/components/Composer/Composer.js +1 -1
- package/lib/cjs/components/Composer/Layer/AudienceLayer/AudienceLayer.js +3 -3
- package/lib/cjs/components/GroupAutocomplete/GroupAutocomplete.js +1 -1
- package/lib/cjs/components/GroupHeader/GroupHeader.js +2 -1
- package/lib/cjs/components/GroupInviteButton/GroupInviteButton.js +13 -0
- package/lib/cjs/components/GroupInvitedWidget/GroupInvitedWidget.js +25 -1
- package/lib/cjs/components/PrivateMessageComponent/PrivateMessageComponent.js +1 -0
- package/lib/cjs/components/PrivateMessageSnippets/PrivateMessageSnippets.js +3 -3
- package/lib/cjs/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +6 -0
- package/lib/cjs/components/User/User.d.ts +1 -1
- package/lib/cjs/components/User/User.js +1 -1
- package/lib/cjs/constants/PubSub.d.ts +1 -0
- package/lib/cjs/constants/PubSub.js +1 -0
- package/lib/esm/components/Composer/Composer.js +1 -1
- package/lib/esm/components/Composer/Layer/AudienceLayer/AudienceLayer.js +3 -3
- package/lib/esm/components/GroupAutocomplete/GroupAutocomplete.js +1 -1
- package/lib/esm/components/GroupHeader/GroupHeader.js +2 -1
- package/lib/esm/components/GroupInviteButton/GroupInviteButton.js +13 -0
- package/lib/esm/components/GroupInvitedWidget/GroupInvitedWidget.js +26 -2
- package/lib/esm/components/PrivateMessageComponent/PrivateMessageComponent.js +1 -0
- package/lib/esm/components/PrivateMessageSnippets/PrivateMessageSnippets.js +3 -3
- package/lib/esm/components/PrivateMessageThreadItem/PrivateMessageThreadItem.js +7 -1
- package/lib/esm/components/User/User.d.ts +1 -1
- package/lib/esm/components/User/User.js +1 -1
- package/lib/esm/constants/PubSub.d.ts +1 -0
- package/lib/esm/constants/PubSub.js +1 -0
- package/lib/umd/react-ui.js +1 -1
- package/package.json +4 -4
|
@@ -307,7 +307,7 @@ function Composer(inProps) {
|
|
|
307
307
|
}
|
|
308
308
|
}), [handleAddLayer, handleRemoveLayer, handleChangeCategories, categories]);
|
|
309
309
|
const handleChangeAudience = (0, react_1.useCallback)((value) => {
|
|
310
|
-
if (group ||
|
|
310
|
+
if (group || Object.prototype.hasOwnProperty.call(value, 'managed_by')) {
|
|
311
311
|
dispatch({ type: 'group', value });
|
|
312
312
|
}
|
|
313
313
|
else {
|
|
@@ -46,7 +46,7 @@ const AudienceLayer = react_1.default.forwardRef((props, ref) => {
|
|
|
46
46
|
// @ts-ignore
|
|
47
47
|
defaultValue === null || defaultValue.length === 0
|
|
48
48
|
? AudienceTypes.AUDIENCE_ALL
|
|
49
|
-
: defaultValue &&
|
|
49
|
+
: defaultValue && Object.prototype.hasOwnProperty.call(defaultValue, 'managed_by')
|
|
50
50
|
? AudienceTypes.AUDIENCE_GROUP
|
|
51
51
|
: AudienceTypes.AUDIENCE_TAG);
|
|
52
52
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -81,14 +81,14 @@ const AudienceLayer = react_1.default.forwardRef((props, ref) => {
|
|
|
81
81
|
, {
|
|
82
82
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
83
83
|
// @ts-ignore
|
|
84
|
-
disabled: defaultValue &&
|
|
84
|
+
disabled: defaultValue && !Object.prototype.hasOwnProperty.call(value, 'managed_by'), value: AudienceTypes.AUDIENCE_GROUP, icon: react_1.default.createElement(Icon_1.default, null, "groups"), label: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.group", defaultMessage: "ui.composer.layer.audience.group" }) }),
|
|
85
85
|
react_1.default.createElement(material_1.Tab
|
|
86
86
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
87
87
|
// @ts-ignore
|
|
88
88
|
, {
|
|
89
89
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
90
90
|
// @ts-ignore
|
|
91
|
-
disabled: value &&
|
|
91
|
+
disabled: value && Object.prototype.hasOwnProperty.call(value, 'managed_by'), value: AudienceTypes.AUDIENCE_TAG, icon: react_1.default.createElement(Icon_1.default, null, "label"), label: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.tag", defaultMessage: "ui.composer.layer.audience.tag" }) })),
|
|
92
92
|
react_1.default.createElement(material_1.Typography, { className: classes.message },
|
|
93
93
|
audience === AudienceTypes.AUDIENCE_ALL && (react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.all.message", defaultMessage: "ui.composer.audience.layer.all.message" })),
|
|
94
94
|
audience === AudienceTypes.AUDIENCE_GROUP && (react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.composer.layer.audience.group.message", defaultMessage: "ui.composer.audience.layer.group.message" })),
|
|
@@ -80,7 +80,7 @@ const GroupAutocomplete = (inProps) => {
|
|
|
80
80
|
setValue(value);
|
|
81
81
|
};
|
|
82
82
|
// Render
|
|
83
|
-
return (react_1.default.createElement(Root, Object.assign({
|
|
83
|
+
return (react_1.default.createElement(Root, Object.assign({ className: classes.root, open: open, onOpen: handleOpen, onClose: handleClose, options: groups || [], getOptionLabel: (option) => option.name || '', value: value, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.groupAutocomplete.empty", defaultMessage: "ui.groupAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, value) => value.id === option.id,
|
|
84
84
|
// renderTags={(value, getTagProps) => {
|
|
85
85
|
// return value.map((option: any, index) => (
|
|
86
86
|
// <Chip key={option.id} id={option.id} label={option.name} color={option.color} {...getTagProps({index})} />
|
|
@@ -115,7 +115,8 @@ function GroupHeader(inProps) {
|
|
|
115
115
|
* Subscriber for pubsub callback
|
|
116
116
|
*/
|
|
117
117
|
const onChangeGroupMembersHandler = (0, react_1.useCallback)((msg, data) => {
|
|
118
|
-
|
|
118
|
+
var _a;
|
|
119
|
+
if (data && ((_a = data === null || data === void 0 ? void 0 : data.group) === null || _a === void 0 ? void 0 : _a.id) === (scGroup === null || scGroup === void 0 ? void 0 : scGroup.id)) {
|
|
119
120
|
let _group = Object.assign({}, scGroup);
|
|
120
121
|
if (msg === `${PubSub_1.SCTopicType.GROUP}.${PubSub_1.SCEventType.ADD_MEMBER}`) {
|
|
121
122
|
_group.subscribers_counter = _group.subscribers_counter + 1;
|
|
@@ -15,6 +15,8 @@ const Autocomplete_1 = tslib_1.__importDefault(require("@mui/material/Autocomple
|
|
|
15
15
|
const User_1 = tslib_1.__importDefault(require("../User"));
|
|
16
16
|
const Errors_1 = require("../../constants/Errors");
|
|
17
17
|
const utils_1 = require("@selfcommunity/utils");
|
|
18
|
+
const PubSub_1 = require("../../constants/PubSub");
|
|
19
|
+
const pubsub_js_1 = tslib_1.__importDefault(require("pubsub-js"));
|
|
18
20
|
const messages = (0, react_intl_1.defineMessages)({
|
|
19
21
|
placeholder: {
|
|
20
22
|
id: 'ui.groupInviteButton.searchBar.placeholder',
|
|
@@ -90,6 +92,16 @@ function GroupInviteButton(inProps) {
|
|
|
90
92
|
const [list, setList] = (0, react_1.useState)([]);
|
|
91
93
|
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
92
94
|
const [invited, setInvited] = (0, react_1.useState)([]);
|
|
95
|
+
/**
|
|
96
|
+
* Notify UI when a member is invited to a group
|
|
97
|
+
* @param group
|
|
98
|
+
* @param usersInvited
|
|
99
|
+
*/
|
|
100
|
+
function notifyChanges(group, usersInvited) {
|
|
101
|
+
if (group && usersInvited) {
|
|
102
|
+
pubsub_js_1.default.publish(`${PubSub_1.SCTopicType.GROUP}.${PubSub_1.SCEventType.INVITE_MEMBER}`, usersInvited);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
93
105
|
function convertToInvitedUsersObject(data) {
|
|
94
106
|
const invite_users = {};
|
|
95
107
|
data.forEach((user, index) => {
|
|
@@ -182,6 +194,7 @@ function GroupInviteButton(inProps) {
|
|
|
182
194
|
setIsSending(false);
|
|
183
195
|
setOpen(false);
|
|
184
196
|
setInvited([]);
|
|
197
|
+
notifyChanges(scGroup, invited);
|
|
185
198
|
})
|
|
186
199
|
.catch((error) => {
|
|
187
200
|
setOpen(false);
|
|
@@ -20,6 +20,8 @@ const system_1 = require("@mui/system");
|
|
|
20
20
|
const HiddenPlaceholder_1 = tslib_1.__importDefault(require("../../shared/HiddenPlaceholder"));
|
|
21
21
|
const constants_1 = require("./constants");
|
|
22
22
|
const User_1 = tslib_1.__importStar(require("../User"));
|
|
23
|
+
const pubsub_js_1 = tslib_1.__importDefault(require("pubsub-js"));
|
|
24
|
+
const PubSub_1 = require("../../constants/PubSub");
|
|
23
25
|
const classes = {
|
|
24
26
|
root: `${constants_1.PREFIX}-root`,
|
|
25
27
|
title: `${constants_1.PREFIX}-title`,
|
|
@@ -95,6 +97,8 @@ function GroupInvitedWidget(inProps) {
|
|
|
95
97
|
const theme = (0, material_1.useTheme)();
|
|
96
98
|
const isMobile = (0, material_1.useMediaQuery)(theme.breakpoints.down('md'));
|
|
97
99
|
const isGroupAdmin = (0, react_1.useMemo)(() => { var _a; return scUserContext.user && ((_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id) === scUserContext.user.id; }, [scUserContext.user, (_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id]);
|
|
100
|
+
// REFS
|
|
101
|
+
const updatesSubscription = (0, react_1.useRef)(null);
|
|
98
102
|
/**
|
|
99
103
|
* Initialize component
|
|
100
104
|
* Fetch data only if the component is not initialized and it is not loading data
|
|
@@ -155,13 +159,33 @@ function GroupInvitedWidget(inProps) {
|
|
|
155
159
|
return;
|
|
156
160
|
}
|
|
157
161
|
}, []);
|
|
162
|
+
/**
|
|
163
|
+
* Subscriber for pubsub callback
|
|
164
|
+
*/
|
|
165
|
+
const onChangeGroupHandler = (0, react_1.useCallback)((_msg, newInvited) => {
|
|
166
|
+
dispatch({
|
|
167
|
+
type: widget_1.actionWidgetTypes.SET_RESULTS,
|
|
168
|
+
payload: { results: [...state.results, ...newInvited] }
|
|
169
|
+
});
|
|
170
|
+
}, [scGroup, dispatch, state.results]);
|
|
171
|
+
/**
|
|
172
|
+
* On mount, subscribe to receive groups updates (only edit)
|
|
173
|
+
*/
|
|
174
|
+
(0, react_1.useEffect)(() => {
|
|
175
|
+
if (scGroup && state.results) {
|
|
176
|
+
updatesSubscription.current = pubsub_js_1.default.subscribe(`${PubSub_1.SCTopicType.GROUP}.${PubSub_1.SCEventType.INVITE_MEMBER}`, onChangeGroupHandler);
|
|
177
|
+
}
|
|
178
|
+
return () => {
|
|
179
|
+
updatesSubscription.current && pubsub_js_1.default.unsubscribe(updatesSubscription.current);
|
|
180
|
+
};
|
|
181
|
+
}, [scGroup, state.results]);
|
|
158
182
|
// HANDLERS
|
|
159
183
|
const handleNext = (0, react_1.useMemo)(() => () => {
|
|
160
184
|
dispatch({ type: widget_1.actionWidgetTypes.LOADING_NEXT });
|
|
161
185
|
api_services_1.http
|
|
162
186
|
.request({
|
|
163
187
|
url: state.next,
|
|
164
|
-
method: api_services_1.Endpoints.
|
|
188
|
+
method: api_services_1.Endpoints.getGroupInvitedUsers.method
|
|
165
189
|
})
|
|
166
190
|
.then((res) => {
|
|
167
191
|
dispatch({ type: widget_1.actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: res.data });
|
|
@@ -109,13 +109,13 @@ function PrivateMessageSnippets(inProps) {
|
|
|
109
109
|
const isSelected = (0, react_1.useMemo)(() => {
|
|
110
110
|
return (message) => {
|
|
111
111
|
var _a, _b;
|
|
112
|
-
if (type === types_1.SCPrivateMessageType.GROUP) {
|
|
112
|
+
if (threadObj && type === types_1.SCPrivateMessageType.GROUP) {
|
|
113
113
|
return ((_a = message === null || message === void 0 ? void 0 : message.group) === null || _a === void 0 ? void 0 : _a.id) === (isObj ? (_b = threadObj === null || threadObj === void 0 ? void 0 : threadObj.group) === null || _b === void 0 ? void 0 : _b.id : threadObj);
|
|
114
114
|
}
|
|
115
|
-
else if (type === types_1.SCPrivateMessageType.USER) {
|
|
115
|
+
else if (threadObj && type === types_1.SCPrivateMessageType.USER) {
|
|
116
116
|
return messageReceiver(message, authUserId) === (isObj ? messageReceiver(threadObj, authUserId) : threadObj);
|
|
117
117
|
}
|
|
118
|
-
return
|
|
118
|
+
return null;
|
|
119
119
|
};
|
|
120
120
|
}, [threadObj, authUserId, type]);
|
|
121
121
|
//HANDLERS
|
|
@@ -10,6 +10,7 @@ const types_1 = require("@selfcommunity/types");
|
|
|
10
10
|
const Icon_1 = tslib_1.__importDefault(require("@mui/material/Icon"));
|
|
11
11
|
const classnames_1 = tslib_1.__importDefault(require("classnames"));
|
|
12
12
|
const system_1 = require("@mui/system");
|
|
13
|
+
const react_core_1 = require("@selfcommunity/react-core");
|
|
13
14
|
const useMediaQuery_1 = tslib_1.__importDefault(require("@mui/material/useMediaQuery"));
|
|
14
15
|
const PrivateMessageSettingsIconButton_1 = tslib_1.__importDefault(require("../PrivateMessageSettingsIconButton"));
|
|
15
16
|
const sizeCoverter_1 = require("../../utils/sizeCoverter");
|
|
@@ -21,6 +22,7 @@ const constants_1 = require("./constants");
|
|
|
21
22
|
const thumbnailCoverter_1 = require("../../utils/thumbnailCoverter");
|
|
22
23
|
const classes = {
|
|
23
24
|
root: `${constants_1.PREFIX}-root`,
|
|
25
|
+
username: `${constants_1.PREFIX}-username`,
|
|
24
26
|
text: `${constants_1.PREFIX}-text`,
|
|
25
27
|
img: `${constants_1.PREFIX}-img`,
|
|
26
28
|
document: `${constants_1.PREFIX}-document`,
|
|
@@ -72,6 +74,7 @@ const Root = (0, styles_1.styled)(material_1.ListItem, {
|
|
|
72
74
|
* @param inProps
|
|
73
75
|
*/
|
|
74
76
|
function PrivateMessageThreadItem(inProps) {
|
|
77
|
+
var _a;
|
|
75
78
|
// PROPS
|
|
76
79
|
const props = (0, system_1.useThemeProps)({
|
|
77
80
|
props: inProps,
|
|
@@ -80,6 +83,8 @@ function PrivateMessageThreadItem(inProps) {
|
|
|
80
83
|
const { message = null, className = null, mouseEvents = {}, isHovering = null, showMenuIcon = false, onMenuIconClick = null } = props, rest = tslib_1.__rest(props, ["message", "className", "mouseEvents", "isHovering", "showMenuIcon", "onMenuIconClick"]);
|
|
81
84
|
// INTL
|
|
82
85
|
const intl = (0, react_intl_1.useIntl)();
|
|
86
|
+
// CONTEXT
|
|
87
|
+
const scUserContext = (0, react_1.useContext)(react_core_1.SCUserContext);
|
|
83
88
|
// STATE
|
|
84
89
|
const theme = (0, material_1.useTheme)();
|
|
85
90
|
const isMobile = (0, useMediaQuery_1.default)(theme.breakpoints.down('md'));
|
|
@@ -167,6 +172,7 @@ function PrivateMessageThreadItem(inProps) {
|
|
|
167
172
|
return (react_1.default.createElement(Root, Object.assign({ className: (0, classnames_1.default)(classes.root, className) }, getMouseEvents(mouseEvents.onMouseEnter, mouseEvents.onMouseLeave), rest, { secondaryAction: (isHovering || isMobile) &&
|
|
168
173
|
showMenuIcon &&
|
|
169
174
|
message.status !== types_1.SCPrivateMessageStatusType.HIDDEN && react_1.default.createElement(PrivateMessageSettingsIconButton_1.default, { onMenuItemDeleteClick: handleMenuItemClick }) }),
|
|
175
|
+
message.group && ((_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.username) !== message.sender.username && (react_1.default.createElement(material_1.Typography, { color: "secondary", variant: "h4", className: classes.username }, message.sender.username)),
|
|
170
176
|
react_1.default.createElement(react_1.default.Fragment, null,
|
|
171
177
|
hasFile && message.status !== types_1.SCPrivateMessageStatusType.HIDDEN ? (renderMessageFile(message)) : (react_1.default.createElement(material_1.Box, { className: classes.text },
|
|
172
178
|
react_1.default.createElement(material_1.Typography, { component: "span", dangerouslySetInnerHTML: { __html: message.message } }))),
|
|
@@ -67,7 +67,7 @@ function User(inProps) {
|
|
|
67
67
|
props: inProps,
|
|
68
68
|
name: constants_1.PREFIX
|
|
69
69
|
});
|
|
70
|
-
const { userId = null, user = null, handleIgnoreAction, className = null, followConnectUserButtonProps = {}, showFollowers = false, elevation, badgeContent = null, actions = null, isGroupAdmin = false, buttonProps =
|
|
70
|
+
const { userId = null, user = null, handleIgnoreAction, className = null, followConnectUserButtonProps = {}, showFollowers = false, elevation, badgeContent = null, actions = null, isGroupAdmin = false, buttonProps = null } = props, rest = tslib_1.__rest(props, ["userId", "user", "handleIgnoreAction", "className", "followConnectUserButtonProps", "showFollowers", "elevation", "badgeContent", "actions", "isGroupAdmin", "buttonProps"]);
|
|
71
71
|
// STATE
|
|
72
72
|
const { scUser, setSCUser } = (0, react_core_1.useSCFetchUser)({ id: userId, user });
|
|
73
73
|
// CONTEXT
|
|
@@ -17,5 +17,6 @@ var SCEventType;
|
|
|
17
17
|
SCEventType["EDIT"] = "edit";
|
|
18
18
|
SCEventType["MEMBERS"] = "members";
|
|
19
19
|
SCEventType["ADD_MEMBER"] = "members.add_member";
|
|
20
|
+
SCEventType["INVITE_MEMBER"] = "members.invite_member";
|
|
20
21
|
SCEventType["REMOVE_MEMBER"] = "members.remove_member";
|
|
21
22
|
})(SCEventType = exports.SCEventType || (exports.SCEventType = {}));
|
|
@@ -305,7 +305,7 @@ export default function Composer(inProps) {
|
|
|
305
305
|
}
|
|
306
306
|
}), [handleAddLayer, handleRemoveLayer, handleChangeCategories, categories]);
|
|
307
307
|
const handleChangeAudience = useCallback((value) => {
|
|
308
|
-
if (group ||
|
|
308
|
+
if (group || Object.prototype.hasOwnProperty.call(value, 'managed_by')) {
|
|
309
309
|
dispatch({ type: 'group', value });
|
|
310
310
|
}
|
|
311
311
|
else {
|
|
@@ -43,7 +43,7 @@ const AudienceLayer = React.forwardRef((props, ref) => {
|
|
|
43
43
|
// @ts-ignore
|
|
44
44
|
defaultValue === null || defaultValue.length === 0
|
|
45
45
|
? AudienceTypes.AUDIENCE_ALL
|
|
46
|
-
: defaultValue &&
|
|
46
|
+
: defaultValue && Object.prototype.hasOwnProperty.call(defaultValue, 'managed_by')
|
|
47
47
|
? AudienceTypes.AUDIENCE_GROUP
|
|
48
48
|
: AudienceTypes.AUDIENCE_TAG);
|
|
49
49
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
@@ -78,14 +78,14 @@ const AudienceLayer = React.forwardRef((props, ref) => {
|
|
|
78
78
|
, {
|
|
79
79
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
80
80
|
// @ts-ignore
|
|
81
|
-
disabled: defaultValue &&
|
|
81
|
+
disabled: defaultValue && !Object.prototype.hasOwnProperty.call(value, 'managed_by'), value: AudienceTypes.AUDIENCE_GROUP, icon: React.createElement(Icon, null, "groups"), label: React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.group", defaultMessage: "ui.composer.layer.audience.group" }) }),
|
|
82
82
|
React.createElement(Tab
|
|
83
83
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
84
84
|
// @ts-ignore
|
|
85
85
|
, {
|
|
86
86
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
87
87
|
// @ts-ignore
|
|
88
|
-
disabled: value &&
|
|
88
|
+
disabled: value && Object.prototype.hasOwnProperty.call(value, 'managed_by'), value: AudienceTypes.AUDIENCE_TAG, icon: React.createElement(Icon, null, "label"), label: React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.tag", defaultMessage: "ui.composer.layer.audience.tag" }) })),
|
|
89
89
|
React.createElement(Typography, { className: classes.message },
|
|
90
90
|
audience === AudienceTypes.AUDIENCE_ALL && (React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.all.message", defaultMessage: "ui.composer.audience.layer.all.message" })),
|
|
91
91
|
audience === AudienceTypes.AUDIENCE_GROUP && (React.createElement(FormattedMessage, { id: "ui.composer.layer.audience.group.message", defaultMessage: "ui.composer.audience.layer.group.message" })),
|
|
@@ -78,7 +78,7 @@ const GroupAutocomplete = (inProps) => {
|
|
|
78
78
|
setValue(value);
|
|
79
79
|
};
|
|
80
80
|
// Render
|
|
81
|
-
return (React.createElement(Root, Object.assign({
|
|
81
|
+
return (React.createElement(Root, Object.assign({ className: classes.root, open: open, onOpen: handleOpen, onClose: handleClose, options: groups || [], getOptionLabel: (option) => option.name || '', value: value, selectOnFocus: true, clearOnBlur: true, blurOnSelect: true, handleHomeEndKeys: true, clearIcon: null, disabled: disabled || isLoading, noOptionsText: React.createElement(FormattedMessage, { id: "ui.groupAutocomplete.empty", defaultMessage: "ui.groupAutocomplete.empty" }), onChange: handleChange, isOptionEqualToValue: (option, value) => value.id === option.id,
|
|
82
82
|
// renderTags={(value, getTagProps) => {
|
|
83
83
|
// return value.map((option: any, index) => (
|
|
84
84
|
// <Chip key={option.id} id={option.id} label={option.name} color={option.color} {...getTagProps({index})} />
|
|
@@ -113,7 +113,8 @@ export default function GroupHeader(inProps) {
|
|
|
113
113
|
* Subscriber for pubsub callback
|
|
114
114
|
*/
|
|
115
115
|
const onChangeGroupMembersHandler = useCallback((msg, data) => {
|
|
116
|
-
|
|
116
|
+
var _a;
|
|
117
|
+
if (data && ((_a = data === null || data === void 0 ? void 0 : data.group) === null || _a === void 0 ? void 0 : _a.id) === (scGroup === null || scGroup === void 0 ? void 0 : scGroup.id)) {
|
|
117
118
|
let _group = Object.assign({}, scGroup);
|
|
118
119
|
if (msg === `${SCTopicType.GROUP}.${SCEventType.ADD_MEMBER}`) {
|
|
119
120
|
_group.subscribers_counter = _group.subscribers_counter + 1;
|
|
@@ -13,6 +13,8 @@ import Autocomplete from '@mui/material/Autocomplete';
|
|
|
13
13
|
import User from '../User';
|
|
14
14
|
import { SCOPE_SC_UI } from '../../constants/Errors';
|
|
15
15
|
import { Logger } from '@selfcommunity/utils';
|
|
16
|
+
import { SCEventType, SCTopicType } from '../../constants/PubSub';
|
|
17
|
+
import PubSub from 'pubsub-js';
|
|
16
18
|
const messages = defineMessages({
|
|
17
19
|
placeholder: {
|
|
18
20
|
id: 'ui.groupInviteButton.searchBar.placeholder',
|
|
@@ -88,6 +90,16 @@ export default function GroupInviteButton(inProps) {
|
|
|
88
90
|
const [list, setList] = useState([]);
|
|
89
91
|
const [loading, setLoading] = useState(false);
|
|
90
92
|
const [invited, setInvited] = useState([]);
|
|
93
|
+
/**
|
|
94
|
+
* Notify UI when a member is invited to a group
|
|
95
|
+
* @param group
|
|
96
|
+
* @param usersInvited
|
|
97
|
+
*/
|
|
98
|
+
function notifyChanges(group, usersInvited) {
|
|
99
|
+
if (group && usersInvited) {
|
|
100
|
+
PubSub.publish(`${SCTopicType.GROUP}.${SCEventType.INVITE_MEMBER}`, usersInvited);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
91
103
|
function convertToInvitedUsersObject(data) {
|
|
92
104
|
const invite_users = {};
|
|
93
105
|
data.forEach((user, index) => {
|
|
@@ -180,6 +192,7 @@ export default function GroupInviteButton(inProps) {
|
|
|
180
192
|
setIsSending(false);
|
|
181
193
|
setOpen(false);
|
|
182
194
|
setInvited([]);
|
|
195
|
+
notifyChanges(scGroup, invited);
|
|
183
196
|
})
|
|
184
197
|
.catch((error) => {
|
|
185
198
|
setOpen(false);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __rest } from "tslib";
|
|
2
|
-
import React, { useEffect, useMemo, useReducer, useState } from 'react';
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useReducer, useRef, useState } from 'react';
|
|
3
3
|
import { styled } from '@mui/material/styles';
|
|
4
4
|
import List from '@mui/material/List';
|
|
5
5
|
import { Button, CardContent, ListItem, Typography, useMediaQuery, useTheme } from '@mui/material';
|
|
@@ -18,6 +18,8 @@ import { useThemeProps } from '@mui/system';
|
|
|
18
18
|
import HiddenPlaceholder from '../../shared/HiddenPlaceholder';
|
|
19
19
|
import { PREFIX } from './constants';
|
|
20
20
|
import User, { UserSkeleton } from '../User';
|
|
21
|
+
import PubSub from 'pubsub-js';
|
|
22
|
+
import { SCEventType, SCTopicType } from '../../constants/PubSub';
|
|
21
23
|
const classes = {
|
|
22
24
|
root: `${PREFIX}-root`,
|
|
23
25
|
title: `${PREFIX}-title`,
|
|
@@ -93,6 +95,8 @@ export default function GroupInvitedWidget(inProps) {
|
|
|
93
95
|
const theme = useTheme();
|
|
94
96
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
|
95
97
|
const isGroupAdmin = useMemo(() => { var _a; return scUserContext.user && ((_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id) === scUserContext.user.id; }, [scUserContext.user, (_a = scGroup === null || scGroup === void 0 ? void 0 : scGroup.managed_by) === null || _a === void 0 ? void 0 : _a.id]);
|
|
98
|
+
// REFS
|
|
99
|
+
const updatesSubscription = useRef(null);
|
|
96
100
|
/**
|
|
97
101
|
* Initialize component
|
|
98
102
|
* Fetch data only if the component is not initialized and it is not loading data
|
|
@@ -153,13 +157,33 @@ export default function GroupInvitedWidget(inProps) {
|
|
|
153
157
|
return;
|
|
154
158
|
}
|
|
155
159
|
}, []);
|
|
160
|
+
/**
|
|
161
|
+
* Subscriber for pubsub callback
|
|
162
|
+
*/
|
|
163
|
+
const onChangeGroupHandler = useCallback((_msg, newInvited) => {
|
|
164
|
+
dispatch({
|
|
165
|
+
type: actionWidgetTypes.SET_RESULTS,
|
|
166
|
+
payload: { results: [...state.results, ...newInvited] }
|
|
167
|
+
});
|
|
168
|
+
}, [scGroup, dispatch, state.results]);
|
|
169
|
+
/**
|
|
170
|
+
* On mount, subscribe to receive groups updates (only edit)
|
|
171
|
+
*/
|
|
172
|
+
useEffect(() => {
|
|
173
|
+
if (scGroup && state.results) {
|
|
174
|
+
updatesSubscription.current = PubSub.subscribe(`${SCTopicType.GROUP}.${SCEventType.INVITE_MEMBER}`, onChangeGroupHandler);
|
|
175
|
+
}
|
|
176
|
+
return () => {
|
|
177
|
+
updatesSubscription.current && PubSub.unsubscribe(updatesSubscription.current);
|
|
178
|
+
};
|
|
179
|
+
}, [scGroup, state.results]);
|
|
156
180
|
// HANDLERS
|
|
157
181
|
const handleNext = useMemo(() => () => {
|
|
158
182
|
dispatch({ type: actionWidgetTypes.LOADING_NEXT });
|
|
159
183
|
http
|
|
160
184
|
.request({
|
|
161
185
|
url: state.next,
|
|
162
|
-
method: Endpoints.
|
|
186
|
+
method: Endpoints.getGroupInvitedUsers.method
|
|
163
187
|
})
|
|
164
188
|
.then((res) => {
|
|
165
189
|
dispatch({ type: actionWidgetTypes.LOAD_NEXT_SUCCESS, payload: res.data });
|
|
@@ -107,13 +107,13 @@ export default function PrivateMessageSnippets(inProps) {
|
|
|
107
107
|
const isSelected = useMemo(() => {
|
|
108
108
|
return (message) => {
|
|
109
109
|
var _a, _b;
|
|
110
|
-
if (type === SCPrivateMessageType.GROUP) {
|
|
110
|
+
if (threadObj && type === SCPrivateMessageType.GROUP) {
|
|
111
111
|
return ((_a = message === null || message === void 0 ? void 0 : message.group) === null || _a === void 0 ? void 0 : _a.id) === (isObj ? (_b = threadObj === null || threadObj === void 0 ? void 0 : threadObj.group) === null || _b === void 0 ? void 0 : _b.id : threadObj);
|
|
112
112
|
}
|
|
113
|
-
else if (type === SCPrivateMessageType.USER) {
|
|
113
|
+
else if (threadObj && type === SCPrivateMessageType.USER) {
|
|
114
114
|
return messageReceiver(message, authUserId) === (isObj ? messageReceiver(threadObj, authUserId) : threadObj);
|
|
115
115
|
}
|
|
116
|
-
return
|
|
116
|
+
return null;
|
|
117
117
|
};
|
|
118
118
|
}, [threadObj, authUserId, type]);
|
|
119
119
|
//HANDLERS
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __awaiter, __rest } from "tslib";
|
|
2
|
-
import React, { useState } from 'react';
|
|
2
|
+
import React, { useContext, useState } from 'react';
|
|
3
3
|
import { styled } from '@mui/material/styles';
|
|
4
4
|
import { ListItem, Typography, IconButton, Box, useTheme, Button } from '@mui/material';
|
|
5
5
|
import PrivateMessageThreadItemSkeleton from './Skeleton';
|
|
@@ -8,6 +8,7 @@ import { SCMessageFileType, SCPrivateMessageStatusType } from '@selfcommunity/ty
|
|
|
8
8
|
import Icon from '@mui/material/Icon';
|
|
9
9
|
import classNames from 'classnames';
|
|
10
10
|
import { useThemeProps } from '@mui/system';
|
|
11
|
+
import { SCUserContext } from '@selfcommunity/react-core';
|
|
11
12
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
|
12
13
|
import PrivateMessageSettingsIconButton from '../PrivateMessageSettingsIconButton';
|
|
13
14
|
import { bytesToSize } from '../../utils/sizeCoverter';
|
|
@@ -19,6 +20,7 @@ import { PREFIX } from './constants';
|
|
|
19
20
|
import { isSupportedVideoFormat } from '../../utils/thumbnailCoverter';
|
|
20
21
|
const classes = {
|
|
21
22
|
root: `${PREFIX}-root`,
|
|
23
|
+
username: `${PREFIX}-username`,
|
|
22
24
|
text: `${PREFIX}-text`,
|
|
23
25
|
img: `${PREFIX}-img`,
|
|
24
26
|
document: `${PREFIX}-document`,
|
|
@@ -70,6 +72,7 @@ const Root = styled(ListItem, {
|
|
|
70
72
|
* @param inProps
|
|
71
73
|
*/
|
|
72
74
|
export default function PrivateMessageThreadItem(inProps) {
|
|
75
|
+
var _a;
|
|
73
76
|
// PROPS
|
|
74
77
|
const props = useThemeProps({
|
|
75
78
|
props: inProps,
|
|
@@ -78,6 +81,8 @@ export default function PrivateMessageThreadItem(inProps) {
|
|
|
78
81
|
const { message = null, className = null, mouseEvents = {}, isHovering = null, showMenuIcon = false, onMenuIconClick = null } = props, rest = __rest(props, ["message", "className", "mouseEvents", "isHovering", "showMenuIcon", "onMenuIconClick"]);
|
|
79
82
|
// INTL
|
|
80
83
|
const intl = useIntl();
|
|
84
|
+
// CONTEXT
|
|
85
|
+
const scUserContext = useContext(SCUserContext);
|
|
81
86
|
// STATE
|
|
82
87
|
const theme = useTheme();
|
|
83
88
|
const isMobile = useMediaQuery(theme.breakpoints.down('md'));
|
|
@@ -165,6 +170,7 @@ export default function PrivateMessageThreadItem(inProps) {
|
|
|
165
170
|
return (React.createElement(Root, Object.assign({ className: classNames(classes.root, className) }, getMouseEvents(mouseEvents.onMouseEnter, mouseEvents.onMouseLeave), rest, { secondaryAction: (isHovering || isMobile) &&
|
|
166
171
|
showMenuIcon &&
|
|
167
172
|
message.status !== SCPrivateMessageStatusType.HIDDEN && React.createElement(PrivateMessageSettingsIconButton, { onMenuItemDeleteClick: handleMenuItemClick }) }),
|
|
173
|
+
message.group && ((_a = scUserContext === null || scUserContext === void 0 ? void 0 : scUserContext.user) === null || _a === void 0 ? void 0 : _a.username) !== message.sender.username && (React.createElement(Typography, { color: "secondary", variant: "h4", className: classes.username }, message.sender.username)),
|
|
168
174
|
React.createElement(React.Fragment, null,
|
|
169
175
|
hasFile && message.status !== SCPrivateMessageStatusType.HIDDEN ? (renderMessageFile(message)) : (React.createElement(Box, { className: classes.text },
|
|
170
176
|
React.createElement(Typography, { component: "span", dangerouslySetInnerHTML: { __html: message.message } }))),
|
|
@@ -65,7 +65,7 @@ export default function User(inProps) {
|
|
|
65
65
|
props: inProps,
|
|
66
66
|
name: PREFIX
|
|
67
67
|
});
|
|
68
|
-
const { userId = null, user = null, handleIgnoreAction, className = null, followConnectUserButtonProps = {}, showFollowers = false, elevation, badgeContent = null, actions = null, isGroupAdmin = false, buttonProps =
|
|
68
|
+
const { userId = null, user = null, handleIgnoreAction, className = null, followConnectUserButtonProps = {}, showFollowers = false, elevation, badgeContent = null, actions = null, isGroupAdmin = false, buttonProps = null } = props, rest = __rest(props, ["userId", "user", "handleIgnoreAction", "className", "followConnectUserButtonProps", "showFollowers", "elevation", "badgeContent", "actions", "isGroupAdmin", "buttonProps"]);
|
|
69
69
|
// STATE
|
|
70
70
|
const { scUser, setSCUser } = useSCFetchUser({ id: userId, user });
|
|
71
71
|
// CONTEXT
|
|
@@ -14,5 +14,6 @@ export var SCEventType;
|
|
|
14
14
|
SCEventType["EDIT"] = "edit";
|
|
15
15
|
SCEventType["MEMBERS"] = "members";
|
|
16
16
|
SCEventType["ADD_MEMBER"] = "members.add_member";
|
|
17
|
+
SCEventType["INVITE_MEMBER"] = "members.invite_member";
|
|
17
18
|
SCEventType["REMOVE_MEMBER"] = "members.remove_member";
|
|
18
19
|
})(SCEventType || (SCEventType = {}));
|