@selfcommunity/react-ui 0.7.0-alpha.316 → 0.7.0-alpha.318
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/CategoriesPopularWidget/CategoriesPopularWidget.d.ts +1 -1
- package/lib/cjs/components/CategoriesPopularWidget/CategoriesPopularWidget.js +1 -1
- package/lib/cjs/components/CommentObject/CommentObject.js +7 -1
- package/lib/cjs/components/FeedObject/FeedObject.d.ts +5 -0
- package/lib/cjs/components/FeedObject/FeedObject.js +45 -15
- package/lib/cjs/constants/Feed.d.ts +1 -0
- package/lib/cjs/constants/Feed.js +2 -1
- package/lib/cjs/utils/contribution.d.ts +2 -2
- package/lib/cjs/utils/contribution.js +3 -3
- package/lib/esm/components/CategoriesPopularWidget/CategoriesPopularWidget.d.ts +1 -1
- package/lib/esm/components/CategoriesPopularWidget/CategoriesPopularWidget.js +1 -1
- package/lib/esm/components/CommentObject/CommentObject.js +7 -1
- package/lib/esm/components/FeedObject/FeedObject.d.ts +5 -0
- package/lib/esm/components/FeedObject/FeedObject.js +45 -15
- package/lib/esm/constants/Feed.d.ts +1 -0
- package/lib/esm/constants/Feed.js +1 -0
- package/lib/esm/utils/contribution.d.ts +2 -2
- package/lib/esm/utils/contribution.js +3 -3
- package/lib/umd/react-ui.js +1 -1
- package/package.json +6 -6
|
@@ -40,7 +40,7 @@ export interface CategoriesPopularWidgetProps extends VirtualScrollerItemProps,
|
|
|
40
40
|
*
|
|
41
41
|
* This component renders a list of popular categories.
|
|
42
42
|
* Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/CategoriesPopular)
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
#### Import
|
|
45
45
|
```jsx
|
|
46
46
|
import {CategoriesPopular} from '@selfcommunity/react-ui';
|
|
@@ -43,7 +43,7 @@ const DialogRoot = (0, styles_1.styled)(BaseDialog_1.default, {
|
|
|
43
43
|
*
|
|
44
44
|
* This component renders a list of popular categories.
|
|
45
45
|
* Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/CategoriesPopular)
|
|
46
|
-
|
|
46
|
+
|
|
47
47
|
#### Import
|
|
48
48
|
```jsx
|
|
49
49
|
import {CategoriesPopular} from '@selfcommunity/react-ui';
|
|
@@ -34,6 +34,7 @@ const classes = {
|
|
|
34
34
|
nestedComments: `${PREFIX}-nested-comments`,
|
|
35
35
|
avatar: `${PREFIX}-avatar`,
|
|
36
36
|
content: `${PREFIX}-content`,
|
|
37
|
+
showMoreContent: `${PREFIX}-show-more-content`,
|
|
37
38
|
author: `${PREFIX}-author`,
|
|
38
39
|
textContent: `${PREFIX}-text-content`,
|
|
39
40
|
commentActionsMenu: `${PREFIX}-comment-actions-menu`,
|
|
@@ -328,6 +329,9 @@ function CommentObject(inProps) {
|
|
|
328
329
|
// or the comment author is the logged user
|
|
329
330
|
return null;
|
|
330
331
|
}
|
|
332
|
+
const commentHtml = comment.summary_html ? comment.summary_html : comment.html;
|
|
333
|
+
const summaryHtmlTruncated = comment.summary_truncated ? comment.summary_truncated : false;
|
|
334
|
+
const summaryHtml = (0, contribution_1.getContributionHtml)(commentHtml, scRoutingContext.url);
|
|
331
335
|
return (react_1.default.createElement(react_1.default.Fragment, { key: comment.id },
|
|
332
336
|
editComment && editComment.id === comment.id ? (react_1.default.createElement(material_1.Box, { className: classes.comment },
|
|
333
337
|
react_1.default.createElement(CommentObjectReply_1.default, Object.assign({ text: comment.html, autoFocus: true, id: `edit-${comment.id}`, onSave: handleSave, onCancel: handleCancel, editable: !isReplying || !isSavingComment }, CommentObjectReplyProps)))) : (react_1.default.createElement(BaseItem_1.default, { elevation: 0, className: classes.comment, image: react_1.default.createElement(react_core_1.Link, Object.assign({}, (!comment.author.deleted && { to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, comment.author) }), { onClick: comment.author.deleted ? () => setOpenAlert(true) : null }),
|
|
@@ -337,7 +341,9 @@ function CommentObject(inProps) {
|
|
|
337
341
|
react_1.default.createElement(material_1.CardContent, { className: (0, classnames_1.default)({ [classes.deleted]: obj && obj.deleted }) },
|
|
338
342
|
react_1.default.createElement(react_core_1.Link, Object.assign({ className: classes.author }, (!comment.author.deleted && { to: scRoutingContext.url(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, comment.author) }), { onClick: comment.author.deleted ? () => setOpenAlert(true) : null }),
|
|
339
343
|
react_1.default.createElement(material_1.Typography, { component: "span" }, comment.author.username)),
|
|
340
|
-
react_1.default.createElement(material_1.Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html:
|
|
344
|
+
react_1.default.createElement(material_1.Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: summaryHtml } }),
|
|
345
|
+
summaryHtmlTruncated && (react_1.default.createElement(react_core_1.Link, { to: scRoutingContext.url(react_core_1.SCRoutes.COMMENT_ROUTE_NAME, (0, contribution_1.getRouteData)(comment)), className: classes.showMoreContent },
|
|
346
|
+
react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.commentObject.showMore", defaultMessage: "ui.commentObject.showMore" })))),
|
|
341
347
|
scUserContext.user && (react_1.default.createElement(material_1.Box, { className: classes.commentActionsMenu },
|
|
342
348
|
react_1.default.createElement(ContributionActionsMenu_1.default, { commentObject: comment, onRestoreContribution: handleRestore, onHideContribution: handleHide, onDeleteContribution: handleDelete, onEditContribution: handleEdit })))),
|
|
343
349
|
react_1.default.createElement(material_1.Box, { component: "span", className: classes.contentSubSection },
|
|
@@ -59,6 +59,11 @@ export interface FeedObjectProps extends CardProps, VirtualScrollerItemProps {
|
|
|
59
59
|
* @default false
|
|
60
60
|
*/
|
|
61
61
|
hideFollowAction?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Show all summary initially (otherwise it will be truncated)
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
summaryExpanded?: boolean;
|
|
62
67
|
/**
|
|
63
68
|
* Show activities as default
|
|
64
69
|
* @default false
|
|
@@ -15,7 +15,6 @@ const Icon_1 = tslib_1.__importDefault(require("@mui/material/Icon"));
|
|
|
15
15
|
const react_intl_1 = require("react-intl");
|
|
16
16
|
const Poll_1 = tslib_1.__importDefault(require("./Poll"));
|
|
17
17
|
const Contributors_1 = tslib_1.__importDefault(require("./Contributors"));
|
|
18
|
-
const Composer_1 = tslib_1.__importDefault(require("../Composer"));
|
|
19
18
|
const feedObject_1 = require("../../types/feedObject");
|
|
20
19
|
const MarkRead_1 = tslib_1.__importDefault(require("../../shared/MarkRead"));
|
|
21
20
|
const classnames_1 = tslib_1.__importDefault(require("classnames"));
|
|
@@ -36,7 +35,8 @@ const errors_1 = require("../../utils/errors");
|
|
|
36
35
|
const react_core_1 = require("@selfcommunity/react-core");
|
|
37
36
|
const UserDeletedSnackBar_1 = tslib_1.__importDefault(require("../../shared/UserDeletedSnackBar"));
|
|
38
37
|
const UserAvatar_1 = tslib_1.__importDefault(require("../../shared/UserAvatar"));
|
|
39
|
-
const
|
|
38
|
+
const Feed_1 = require("../../constants/Feed");
|
|
39
|
+
const Composer_1 = tslib_1.__importDefault(require("../Composer"));
|
|
40
40
|
const messages = (0, react_intl_1.defineMessages)({
|
|
41
41
|
visibleToAll: {
|
|
42
42
|
id: 'ui.feedObject.visibleToAll',
|
|
@@ -133,7 +133,7 @@ function FeedObject(inProps) {
|
|
|
133
133
|
props: inProps,
|
|
134
134
|
name: PREFIX
|
|
135
135
|
});
|
|
136
|
-
const { id = `feed_object_${props.feedObjectId ? props.feedObjectId : props.feedObject ? props.feedObject.id : ''}`, className = null, feedObjectId = null, feedObject = null, feedObjectType = types_1.SCContributionType.DISCUSSION, feedObjectActivities = null, cacheStrategy = utils_1.CacheStrategies.CACHE_FIRST, markRead = false, template = feedObject_1.SCFeedObjectTemplateType.PREVIEW, hideFollowAction = false, activitiesExpanded = true, activitiesExpandedType, hideParticipantsPreview = false, pollVisible = false, FollowButtonProps = {}, FeedObjectSkeletonProps = { elevation: 0 }, ActionsProps = {}, CommentObjectReplyComponent = CommentObjectReply_1.default, CommentObjectReplyComponentProps = { WidgetProps: { variant: 'outlined' } }, CommentComponentProps = { variant: 'outlined' }, CommentObjectSkeletonProps = { elevation: 0, WidgetProps: { variant: 'outlined' } }, ContributionActionsMenuProps = {}, MediasPreviewProps = {}, ActivitiesProps = { cacheStrategy }, PollObjectProps = { elevation: 0 }, ContributorsFeedObjectProps = {}, onReply, onHeightChange, onStateChange } = props, rest = tslib_1.__rest(props, ["id", "className", "feedObjectId", "feedObject", "feedObjectType", "feedObjectActivities", "cacheStrategy", "markRead", "template", "hideFollowAction", "activitiesExpanded", "activitiesExpandedType", "hideParticipantsPreview", "pollVisible", "FollowButtonProps", "FeedObjectSkeletonProps", "ActionsProps", "CommentObjectReplyComponent", "CommentObjectReplyComponentProps", "CommentComponentProps", "CommentObjectSkeletonProps", "ContributionActionsMenuProps", "MediasPreviewProps", "ActivitiesProps", "PollObjectProps", "ContributorsFeedObjectProps", "onReply", "onHeightChange", "onStateChange"]);
|
|
136
|
+
const { id = `feed_object_${props.feedObjectId ? props.feedObjectId : props.feedObject ? props.feedObject.id : ''}`, className = null, feedObjectId = null, feedObject = null, feedObjectType = types_1.SCContributionType.DISCUSSION, feedObjectActivities = null, cacheStrategy = utils_1.CacheStrategies.CACHE_FIRST, markRead = false, template = feedObject_1.SCFeedObjectTemplateType.PREVIEW, hideFollowAction = false, summaryExpanded = false, activitiesExpanded = true, activitiesExpandedType, hideParticipantsPreview = false, pollVisible = false, FollowButtonProps = {}, FeedObjectSkeletonProps = { elevation: 0 }, ActionsProps = {}, CommentObjectReplyComponent = CommentObjectReply_1.default, CommentObjectReplyComponentProps = { WidgetProps: { variant: 'outlined' } }, CommentComponentProps = { variant: 'outlined' }, CommentObjectSkeletonProps = { elevation: 0, WidgetProps: { variant: 'outlined' } }, ContributionActionsMenuProps = {}, MediasPreviewProps = {}, ActivitiesProps = { cacheStrategy }, PollObjectProps = { elevation: 0 }, ContributorsFeedObjectProps = {}, onReply, onHeightChange, onStateChange } = props, rest = tslib_1.__rest(props, ["id", "className", "feedObjectId", "feedObject", "feedObjectType", "feedObjectActivities", "cacheStrategy", "markRead", "template", "hideFollowAction", "summaryExpanded", "activitiesExpanded", "activitiesExpandedType", "hideParticipantsPreview", "pollVisible", "FollowButtonProps", "FeedObjectSkeletonProps", "ActionsProps", "CommentObjectReplyComponent", "CommentObjectReplyComponentProps", "CommentComponentProps", "CommentObjectSkeletonProps", "ContributionActionsMenuProps", "MediasPreviewProps", "ActivitiesProps", "PollObjectProps", "ContributorsFeedObjectProps", "onReply", "onHeightChange", "onStateChange"]);
|
|
137
137
|
// CONTEXT
|
|
138
138
|
const scContext = (0, react_core_1.useSCContext)();
|
|
139
139
|
const scRoutingContext = (0, react_core_1.useSCRouting)();
|
|
@@ -155,7 +155,7 @@ function FeedObject(inProps) {
|
|
|
155
155
|
const [comments, setComments] = (0, react_1.useState)([]);
|
|
156
156
|
const [isReplying, setIsReplying] = (0, react_1.useState)(false);
|
|
157
157
|
const [selectedActivities, setSelectedActivities] = (0, react_1.useState)(getInitialSelectedActivitiesType());
|
|
158
|
-
const [expanded, setExpanded] = (0, react_1.useState)(
|
|
158
|
+
const [expanded, setExpanded] = (0, react_1.useState)(summaryExpanded);
|
|
159
159
|
// INTL
|
|
160
160
|
const intl = (0, react_intl_1.useIntl)();
|
|
161
161
|
/**
|
|
@@ -207,6 +207,13 @@ function FeedObject(inProps) {
|
|
|
207
207
|
const handleTogglePollVisibility = (0, react_1.useCallback)((visible) => {
|
|
208
208
|
notifyFeedChanges({ pollVisible: visible });
|
|
209
209
|
}, [pollVisible, notifyFeedChanges]);
|
|
210
|
+
/**
|
|
211
|
+
* Handle toggle summary
|
|
212
|
+
*/
|
|
213
|
+
const handleToggleSummary = (0, react_1.useCallback)(() => {
|
|
214
|
+
setExpanded(!expanded);
|
|
215
|
+
notifyFeedChanges({ summaryExpanded: !expanded });
|
|
216
|
+
}, [expanded, notifyFeedChanges]);
|
|
210
217
|
/**
|
|
211
218
|
* Render header action
|
|
212
219
|
* if author = authenticated user -> render edit action
|
|
@@ -369,6 +376,38 @@ function FeedObject(inProps) {
|
|
|
369
376
|
});
|
|
370
377
|
}
|
|
371
378
|
};
|
|
379
|
+
/**
|
|
380
|
+
* Get contribution summary
|
|
381
|
+
*/
|
|
382
|
+
const getContributionSummary = (0, react_1.useCallback)((obj, template) => {
|
|
383
|
+
const contributionHtml = obj.summary_html ? obj.summary_html : obj.summary;
|
|
384
|
+
const summaryHtmlTruncated = obj.summary_truncated ? obj.summary_truncated : obj.html.length >= Feed_1.MAX_SUMMARY_LENGTH;
|
|
385
|
+
const summaryHtml = expanded || template === feedObject_1.SCFeedObjectTemplateType.DETAIL
|
|
386
|
+
? (0, contribution_1.getContributionHtml)(obj.html, scRoutingContext.url)
|
|
387
|
+
: (0, contribution_1.getContributionHtml)(contributionHtml, scRoutingContext.url);
|
|
388
|
+
if (template === feedObject_1.SCFeedObjectTemplateType.SHARE) {
|
|
389
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
390
|
+
react_1.default.createElement(react_core_1.Link, { to: scRoutingContext.url((0, contribution_1.getContributionRouteName)(obj), (0, contribution_1.getRouteData)(obj)), className: classes.text },
|
|
391
|
+
react_1.default.createElement(material_1.Typography, { component: "div", className: classes.text, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: {
|
|
392
|
+
__html: summaryHtml
|
|
393
|
+
} })),
|
|
394
|
+
!expanded && summaryHtmlTruncated && (react_1.default.createElement(material_1.Button, { size: "small", variant: "text", color: "inherit", onClick: handleToggleSummary },
|
|
395
|
+
react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.feedObject.content.showMore", defaultMessage: "ui.feedObject.content.showMore" })))));
|
|
396
|
+
}
|
|
397
|
+
else if (template === feedObject_1.SCFeedObjectTemplateType.DETAIL) {
|
|
398
|
+
return (react_1.default.createElement(material_1.Typography, { component: "div", gutterBottom: true, className: classes.text, dangerouslySetInnerHTML: {
|
|
399
|
+
__html: summaryHtml
|
|
400
|
+
} }));
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
return (react_1.default.createElement(material_1.Typography, { component: "div", gutterBottom: true, className: classes.text },
|
|
404
|
+
react_1.default.createElement(material_1.Typography, { component: "span", dangerouslySetInnerHTML: {
|
|
405
|
+
__html: summaryHtml
|
|
406
|
+
} }),
|
|
407
|
+
!expanded && summaryHtmlTruncated && (react_1.default.createElement(material_1.Button, { size: "small", variant: "text", color: "inherit", onClick: handleToggleSummary },
|
|
408
|
+
react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.feedObject.content.showMore", defaultMessage: "ui.feedObject.content.showMore" })))));
|
|
409
|
+
}
|
|
410
|
+
}, [obj, template, expanded]);
|
|
372
411
|
/**
|
|
373
412
|
* Render the obj object
|
|
374
413
|
* Manage variants:
|
|
@@ -402,12 +441,7 @@ function FeedObject(inProps) {
|
|
|
402
441
|
react_1.default.createElement(CardContent_1.default, { classes: { root: classes.content } },
|
|
403
442
|
react_1.default.createElement(material_1.Box, { className: classes.titleSection }, 'title' in obj && (react_1.default.createElement(react_1.default.Fragment, null, template === feedObject_1.SCFeedObjectTemplateType.DETAIL ? (react_1.default.createElement(material_1.Typography, { variant: "body1", gutterBottom: true, className: classes.title }, obj.title)) : (react_1.default.createElement(react_core_1.Link, { to: scRoutingContext.url((0, contribution_1.getContributionRouteName)(obj), (0, contribution_1.getRouteData)(obj)) },
|
|
404
443
|
react_1.default.createElement(material_1.Typography, { variant: "body1", gutterBottom: true, className: classes.title }, obj.title)))))),
|
|
405
|
-
react_1.default.createElement(material_1.Box, { className: classes.textSection },
|
|
406
|
-
__html: (0, contribution_1.getContributionHtml)(obj, scRoutingContext.url)
|
|
407
|
-
} })) : (react_1.default.createElement(material_1.Typography, { component: "div", gutterBottom: true, className: classes.text },
|
|
408
|
-
react_1.default.createElement(material_1.Typography, { component: "span", dangerouslySetInnerHTML: { __html: expanded ? (0, contribution_1.getContributionHtml)(obj, scRoutingContext.url) : obj.summary } }),
|
|
409
|
-
!expanded && obj.html.length >= MAX_SUMMARY_LENGTH && (react_1.default.createElement(material_1.Button, { size: "small", variant: "text", color: "inherit", onClick: () => setExpanded(!expanded) },
|
|
410
|
-
react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.feedObject.content.showMore", defaultMessage: "ui.feedObject.content.showMore" })))))),
|
|
444
|
+
react_1.default.createElement(material_1.Box, { className: classes.textSection }, getContributionSummary(obj, template)),
|
|
411
445
|
react_1.default.createElement(material_1.Box, { className: classes.mediasSection },
|
|
412
446
|
react_1.default.createElement(MediasPreview_1.default, Object.assign({ medias: obj.medias }, MediasPreviewProps))),
|
|
413
447
|
react_1.default.createElement(material_1.Box, { className: classes.pollsSection }, obj['poll'] && (react_1.default.createElement(Poll_1.default, Object.assign({ visible: pollVisible ||
|
|
@@ -440,11 +474,7 @@ function FeedObject(inProps) {
|
|
|
440
474
|
react_1.default.createElement(CardContent_1.default, { classes: { root: classes.content } },
|
|
441
475
|
react_1.default.createElement(material_1.Box, { className: classes.titleSection }, 'title' in obj && (react_1.default.createElement(react_core_1.Link, { to: scRoutingContext.url((0, contribution_1.getContributionRouteName)(obj), (0, contribution_1.getRouteData)(obj)) },
|
|
442
476
|
react_1.default.createElement(material_1.Typography, { variant: "body1", gutterBottom: true, className: classes.title }, obj.title)))),
|
|
443
|
-
react_1.default.createElement(material_1.Box, { className: classes.textSection },
|
|
444
|
-
react_1.default.createElement(react_core_1.Link, { to: scRoutingContext.url((0, contribution_1.getContributionRouteName)(obj), (0, contribution_1.getRouteData)(obj)), className: classes.text },
|
|
445
|
-
react_1.default.createElement(material_1.Typography, { component: "div", className: classes.text, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: expanded ? (0, contribution_1.getContributionHtml)(obj, scRoutingContext.url) : obj.summary } })),
|
|
446
|
-
!expanded && obj.html.length >= MAX_SUMMARY_LENGTH && (react_1.default.createElement(material_1.Button, { size: "small", variant: "text", color: "inherit", onClick: () => setExpanded(!expanded) },
|
|
447
|
-
react_1.default.createElement(react_intl_1.FormattedMessage, { id: "ui.feedObject.content.showMore", defaultMessage: "ui.feedObject.content.showMore" })))),
|
|
477
|
+
react_1.default.createElement(material_1.Box, { className: classes.textSection }, getContributionSummary(obj, template)),
|
|
448
478
|
react_1.default.createElement(material_1.Box, { className: classes.mediasSection },
|
|
449
479
|
react_1.default.createElement(MediasPreview_1.default, Object.assign({ medias: obj.medias }, MediasPreviewProps))),
|
|
450
480
|
react_1.default.createElement(material_1.Box, { className: classes.pollsSection }, obj['poll'] && (react_1.default.createElement(Poll_1.default, Object.assign({ feedObject: obj, pollObject: obj['poll'], onChange: handleChangePoll, visible: Boolean(obj.type !== types_1.SCContributionType.DISCUSSION && !obj.html && !obj.medias.length) }, PollObjectProps))))))) : (react_1.default.createElement(Skeleton_1.default, Object.assign({ template: template }, FeedObjectSkeletonProps)))));
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.DEFAULT_WIDGETS_NUMBER = exports.WIDGET_PREFIX_KEY = void 0;
|
|
3
|
+
exports.MAX_SUMMARY_LENGTH = exports.DEFAULT_WIDGETS_NUMBER = exports.WIDGET_PREFIX_KEY = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Feed constants
|
|
6
6
|
*/
|
|
7
7
|
exports.WIDGET_PREFIX_KEY = 'widget_';
|
|
8
8
|
exports.DEFAULT_WIDGETS_NUMBER = 10; // every how many elements insert a widget
|
|
9
|
+
exports.MAX_SUMMARY_LENGTH = 150; // maximum number of characters for the summary before being truncated
|
|
@@ -17,10 +17,10 @@ export declare function getContributionSnippet(obj: any): any;
|
|
|
17
17
|
/**
|
|
18
18
|
* Get the contribution text
|
|
19
19
|
* Hydrate text with mention, etc.
|
|
20
|
-
* @param
|
|
20
|
+
* @param html Html of the contribution
|
|
21
21
|
* @param handleUrl Func that handle urls
|
|
22
22
|
*/
|
|
23
|
-
export declare function getContributionHtml(
|
|
23
|
+
export declare function getContributionHtml(html: any, handleUrl: any): any;
|
|
24
24
|
/**
|
|
25
25
|
* Get route name for a contribution
|
|
26
26
|
* @param obj
|
|
@@ -54,11 +54,11 @@ exports.getContributionSnippet = getContributionSnippet;
|
|
|
54
54
|
/**
|
|
55
55
|
* Get the contribution text
|
|
56
56
|
* Hydrate text with mention, etc.
|
|
57
|
-
* @param
|
|
57
|
+
* @param html Html of the contribution
|
|
58
58
|
* @param handleUrl Func that handle urls
|
|
59
59
|
*/
|
|
60
|
-
function getContributionHtml(
|
|
61
|
-
return
|
|
60
|
+
function getContributionHtml(html, handleUrl) {
|
|
61
|
+
return html.replace(/<mention.*? id="([0-9]+)"{1}.*?>@([a-z\d_]+)<\/mention>/gi, (match, id, username) => {
|
|
62
62
|
return `<a href='${handleUrl(react_core_1.SCRoutes.USER_PROFILE_ROUTE_NAME, { id, username })}'>@${username}</a>`;
|
|
63
63
|
});
|
|
64
64
|
}
|
|
@@ -40,7 +40,7 @@ export interface CategoriesPopularWidgetProps extends VirtualScrollerItemProps,
|
|
|
40
40
|
*
|
|
41
41
|
* This component renders a list of popular categories.
|
|
42
42
|
* Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/CategoriesPopular)
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
#### Import
|
|
45
45
|
```jsx
|
|
46
46
|
import {CategoriesPopular} from '@selfcommunity/react-ui';
|
|
@@ -41,7 +41,7 @@ const DialogRoot = styled(BaseDialog, {
|
|
|
41
41
|
*
|
|
42
42
|
* This component renders a list of popular categories.
|
|
43
43
|
* Take a look at our <strong>demo</strong> component [here](/docs/sdk/community-js/react-ui/Components/CategoriesPopular)
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
#### Import
|
|
46
46
|
```jsx
|
|
47
47
|
import {CategoriesPopular} from '@selfcommunity/react-ui';
|
|
@@ -32,6 +32,7 @@ const classes = {
|
|
|
32
32
|
nestedComments: `${PREFIX}-nested-comments`,
|
|
33
33
|
avatar: `${PREFIX}-avatar`,
|
|
34
34
|
content: `${PREFIX}-content`,
|
|
35
|
+
showMoreContent: `${PREFIX}-show-more-content`,
|
|
35
36
|
author: `${PREFIX}-author`,
|
|
36
37
|
textContent: `${PREFIX}-text-content`,
|
|
37
38
|
commentActionsMenu: `${PREFIX}-comment-actions-menu`,
|
|
@@ -326,6 +327,9 @@ export default function CommentObject(inProps) {
|
|
|
326
327
|
// or the comment author is the logged user
|
|
327
328
|
return null;
|
|
328
329
|
}
|
|
330
|
+
const commentHtml = comment.summary_html ? comment.summary_html : comment.html;
|
|
331
|
+
const summaryHtmlTruncated = comment.summary_truncated ? comment.summary_truncated : false;
|
|
332
|
+
const summaryHtml = getContributionHtml(commentHtml, scRoutingContext.url);
|
|
329
333
|
return (React.createElement(React.Fragment, { key: comment.id },
|
|
330
334
|
editComment && editComment.id === comment.id ? (React.createElement(Box, { className: classes.comment },
|
|
331
335
|
React.createElement(CommentObjectReply, Object.assign({ text: comment.html, autoFocus: true, id: `edit-${comment.id}`, onSave: handleSave, onCancel: handleCancel, editable: !isReplying || !isSavingComment }, CommentObjectReplyProps)))) : (React.createElement(BaseItem, { elevation: 0, className: classes.comment, image: React.createElement(Link, Object.assign({}, (!comment.author.deleted && { to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, comment.author) }), { onClick: comment.author.deleted ? () => setOpenAlert(true) : null }),
|
|
@@ -335,7 +339,9 @@ export default function CommentObject(inProps) {
|
|
|
335
339
|
React.createElement(CardContent, { className: classNames({ [classes.deleted]: obj && obj.deleted }) },
|
|
336
340
|
React.createElement(Link, Object.assign({ className: classes.author }, (!comment.author.deleted && { to: scRoutingContext.url(SCRoutes.USER_PROFILE_ROUTE_NAME, comment.author) }), { onClick: comment.author.deleted ? () => setOpenAlert(true) : null }),
|
|
337
341
|
React.createElement(Typography, { component: "span" }, comment.author.username)),
|
|
338
|
-
React.createElement(Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html:
|
|
342
|
+
React.createElement(Typography, { className: classes.textContent, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: summaryHtml } }),
|
|
343
|
+
summaryHtmlTruncated && (React.createElement(Link, { to: scRoutingContext.url(SCRoutes.COMMENT_ROUTE_NAME, getRouteData(comment)), className: classes.showMoreContent },
|
|
344
|
+
React.createElement(FormattedMessage, { id: "ui.commentObject.showMore", defaultMessage: "ui.commentObject.showMore" })))),
|
|
339
345
|
scUserContext.user && (React.createElement(Box, { className: classes.commentActionsMenu },
|
|
340
346
|
React.createElement(ContributionActionsMenu, { commentObject: comment, onRestoreContribution: handleRestore, onHideContribution: handleHide, onDeleteContribution: handleDelete, onEditContribution: handleEdit })))),
|
|
341
347
|
React.createElement(Box, { component: "span", className: classes.contentSubSection },
|
|
@@ -59,6 +59,11 @@ export interface FeedObjectProps extends CardProps, VirtualScrollerItemProps {
|
|
|
59
59
|
* @default false
|
|
60
60
|
*/
|
|
61
61
|
hideFollowAction?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Show all summary initially (otherwise it will be truncated)
|
|
64
|
+
* @default false
|
|
65
|
+
*/
|
|
66
|
+
summaryExpanded?: boolean;
|
|
62
67
|
/**
|
|
63
68
|
* Show activities as default
|
|
64
69
|
* @default false
|
|
@@ -13,7 +13,6 @@ import Icon from '@mui/material/Icon';
|
|
|
13
13
|
import { defineMessages, FormattedMessage, useIntl } from 'react-intl';
|
|
14
14
|
import PollObject from './Poll';
|
|
15
15
|
import ContributorsFeedObject from './Contributors';
|
|
16
|
-
import Composer from '../Composer';
|
|
17
16
|
import { SCFeedObjectActivitiesType, SCFeedObjectTemplateType } from '../../types/feedObject';
|
|
18
17
|
import MarkRead from '../../shared/MarkRead';
|
|
19
18
|
import classNames from 'classnames';
|
|
@@ -34,7 +33,8 @@ import { catchUnauthorizedActionByBlockedUser } from '../../utils/errors';
|
|
|
34
33
|
import { Link, SCCache, SCRoutes, UserUtils, useSCContext, useSCFetchFeedObject, useSCRouting, useSCUser } from '@selfcommunity/react-core';
|
|
35
34
|
import UserDeletedSnackBar from '../../shared/UserDeletedSnackBar';
|
|
36
35
|
import UserAvatar from '../../shared/UserAvatar';
|
|
37
|
-
|
|
36
|
+
import { MAX_SUMMARY_LENGTH } from '../../constants/Feed';
|
|
37
|
+
import Composer from '../Composer';
|
|
38
38
|
const messages = defineMessages({
|
|
39
39
|
visibleToAll: {
|
|
40
40
|
id: 'ui.feedObject.visibleToAll',
|
|
@@ -131,7 +131,7 @@ export default function FeedObject(inProps) {
|
|
|
131
131
|
props: inProps,
|
|
132
132
|
name: PREFIX
|
|
133
133
|
});
|
|
134
|
-
const { id = `feed_object_${props.feedObjectId ? props.feedObjectId : props.feedObject ? props.feedObject.id : ''}`, className = null, feedObjectId = null, feedObject = null, feedObjectType = SCContributionType.DISCUSSION, feedObjectActivities = null, cacheStrategy = CacheStrategies.CACHE_FIRST, markRead = false, template = SCFeedObjectTemplateType.PREVIEW, hideFollowAction = false, activitiesExpanded = true, activitiesExpandedType, hideParticipantsPreview = false, pollVisible = false, FollowButtonProps = {}, FeedObjectSkeletonProps = { elevation: 0 }, ActionsProps = {}, CommentObjectReplyComponent = CommentObjectReply, CommentObjectReplyComponentProps = { WidgetProps: { variant: 'outlined' } }, CommentComponentProps = { variant: 'outlined' }, CommentObjectSkeletonProps = { elevation: 0, WidgetProps: { variant: 'outlined' } }, ContributionActionsMenuProps = {}, MediasPreviewProps = {}, ActivitiesProps = { cacheStrategy }, PollObjectProps = { elevation: 0 }, ContributorsFeedObjectProps = {}, onReply, onHeightChange, onStateChange } = props, rest = __rest(props, ["id", "className", "feedObjectId", "feedObject", "feedObjectType", "feedObjectActivities", "cacheStrategy", "markRead", "template", "hideFollowAction", "activitiesExpanded", "activitiesExpandedType", "hideParticipantsPreview", "pollVisible", "FollowButtonProps", "FeedObjectSkeletonProps", "ActionsProps", "CommentObjectReplyComponent", "CommentObjectReplyComponentProps", "CommentComponentProps", "CommentObjectSkeletonProps", "ContributionActionsMenuProps", "MediasPreviewProps", "ActivitiesProps", "PollObjectProps", "ContributorsFeedObjectProps", "onReply", "onHeightChange", "onStateChange"]);
|
|
134
|
+
const { id = `feed_object_${props.feedObjectId ? props.feedObjectId : props.feedObject ? props.feedObject.id : ''}`, className = null, feedObjectId = null, feedObject = null, feedObjectType = SCContributionType.DISCUSSION, feedObjectActivities = null, cacheStrategy = CacheStrategies.CACHE_FIRST, markRead = false, template = SCFeedObjectTemplateType.PREVIEW, hideFollowAction = false, summaryExpanded = false, activitiesExpanded = true, activitiesExpandedType, hideParticipantsPreview = false, pollVisible = false, FollowButtonProps = {}, FeedObjectSkeletonProps = { elevation: 0 }, ActionsProps = {}, CommentObjectReplyComponent = CommentObjectReply, CommentObjectReplyComponentProps = { WidgetProps: { variant: 'outlined' } }, CommentComponentProps = { variant: 'outlined' }, CommentObjectSkeletonProps = { elevation: 0, WidgetProps: { variant: 'outlined' } }, ContributionActionsMenuProps = {}, MediasPreviewProps = {}, ActivitiesProps = { cacheStrategy }, PollObjectProps = { elevation: 0 }, ContributorsFeedObjectProps = {}, onReply, onHeightChange, onStateChange } = props, rest = __rest(props, ["id", "className", "feedObjectId", "feedObject", "feedObjectType", "feedObjectActivities", "cacheStrategy", "markRead", "template", "hideFollowAction", "summaryExpanded", "activitiesExpanded", "activitiesExpandedType", "hideParticipantsPreview", "pollVisible", "FollowButtonProps", "FeedObjectSkeletonProps", "ActionsProps", "CommentObjectReplyComponent", "CommentObjectReplyComponentProps", "CommentComponentProps", "CommentObjectSkeletonProps", "ContributionActionsMenuProps", "MediasPreviewProps", "ActivitiesProps", "PollObjectProps", "ContributorsFeedObjectProps", "onReply", "onHeightChange", "onStateChange"]);
|
|
135
135
|
// CONTEXT
|
|
136
136
|
const scContext = useSCContext();
|
|
137
137
|
const scRoutingContext = useSCRouting();
|
|
@@ -153,7 +153,7 @@ export default function FeedObject(inProps) {
|
|
|
153
153
|
const [comments, setComments] = useState([]);
|
|
154
154
|
const [isReplying, setIsReplying] = useState(false);
|
|
155
155
|
const [selectedActivities, setSelectedActivities] = useState(getInitialSelectedActivitiesType());
|
|
156
|
-
const [expanded, setExpanded] = useState(
|
|
156
|
+
const [expanded, setExpanded] = useState(summaryExpanded);
|
|
157
157
|
// INTL
|
|
158
158
|
const intl = useIntl();
|
|
159
159
|
/**
|
|
@@ -205,6 +205,13 @@ export default function FeedObject(inProps) {
|
|
|
205
205
|
const handleTogglePollVisibility = useCallback((visible) => {
|
|
206
206
|
notifyFeedChanges({ pollVisible: visible });
|
|
207
207
|
}, [pollVisible, notifyFeedChanges]);
|
|
208
|
+
/**
|
|
209
|
+
* Handle toggle summary
|
|
210
|
+
*/
|
|
211
|
+
const handleToggleSummary = useCallback(() => {
|
|
212
|
+
setExpanded(!expanded);
|
|
213
|
+
notifyFeedChanges({ summaryExpanded: !expanded });
|
|
214
|
+
}, [expanded, notifyFeedChanges]);
|
|
208
215
|
/**
|
|
209
216
|
* Render header action
|
|
210
217
|
* if author = authenticated user -> render edit action
|
|
@@ -367,6 +374,38 @@ export default function FeedObject(inProps) {
|
|
|
367
374
|
});
|
|
368
375
|
}
|
|
369
376
|
};
|
|
377
|
+
/**
|
|
378
|
+
* Get contribution summary
|
|
379
|
+
*/
|
|
380
|
+
const getContributionSummary = useCallback((obj, template) => {
|
|
381
|
+
const contributionHtml = obj.summary_html ? obj.summary_html : obj.summary;
|
|
382
|
+
const summaryHtmlTruncated = obj.summary_truncated ? obj.summary_truncated : obj.html.length >= MAX_SUMMARY_LENGTH;
|
|
383
|
+
const summaryHtml = expanded || template === SCFeedObjectTemplateType.DETAIL
|
|
384
|
+
? getContributionHtml(obj.html, scRoutingContext.url)
|
|
385
|
+
: getContributionHtml(contributionHtml, scRoutingContext.url);
|
|
386
|
+
if (template === SCFeedObjectTemplateType.SHARE) {
|
|
387
|
+
return (React.createElement(React.Fragment, null,
|
|
388
|
+
React.createElement(Link, { to: scRoutingContext.url(getContributionRouteName(obj), getRouteData(obj)), className: classes.text },
|
|
389
|
+
React.createElement(Typography, { component: "div", className: classes.text, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: {
|
|
390
|
+
__html: summaryHtml
|
|
391
|
+
} })),
|
|
392
|
+
!expanded && summaryHtmlTruncated && (React.createElement(Button, { size: "small", variant: "text", color: "inherit", onClick: handleToggleSummary },
|
|
393
|
+
React.createElement(FormattedMessage, { id: "ui.feedObject.content.showMore", defaultMessage: "ui.feedObject.content.showMore" })))));
|
|
394
|
+
}
|
|
395
|
+
else if (template === SCFeedObjectTemplateType.DETAIL) {
|
|
396
|
+
return (React.createElement(Typography, { component: "div", gutterBottom: true, className: classes.text, dangerouslySetInnerHTML: {
|
|
397
|
+
__html: summaryHtml
|
|
398
|
+
} }));
|
|
399
|
+
}
|
|
400
|
+
else {
|
|
401
|
+
return (React.createElement(Typography, { component: "div", gutterBottom: true, className: classes.text },
|
|
402
|
+
React.createElement(Typography, { component: "span", dangerouslySetInnerHTML: {
|
|
403
|
+
__html: summaryHtml
|
|
404
|
+
} }),
|
|
405
|
+
!expanded && summaryHtmlTruncated && (React.createElement(Button, { size: "small", variant: "text", color: "inherit", onClick: handleToggleSummary },
|
|
406
|
+
React.createElement(FormattedMessage, { id: "ui.feedObject.content.showMore", defaultMessage: "ui.feedObject.content.showMore" })))));
|
|
407
|
+
}
|
|
408
|
+
}, [obj, template, expanded]);
|
|
370
409
|
/**
|
|
371
410
|
* Render the obj object
|
|
372
411
|
* Manage variants:
|
|
@@ -400,12 +439,7 @@ export default function FeedObject(inProps) {
|
|
|
400
439
|
React.createElement(CardContent, { classes: { root: classes.content } },
|
|
401
440
|
React.createElement(Box, { className: classes.titleSection }, 'title' in obj && (React.createElement(React.Fragment, null, template === SCFeedObjectTemplateType.DETAIL ? (React.createElement(Typography, { variant: "body1", gutterBottom: true, className: classes.title }, obj.title)) : (React.createElement(Link, { to: scRoutingContext.url(getContributionRouteName(obj), getRouteData(obj)) },
|
|
402
441
|
React.createElement(Typography, { variant: "body1", gutterBottom: true, className: classes.title }, obj.title)))))),
|
|
403
|
-
React.createElement(Box, { className: classes.textSection },
|
|
404
|
-
__html: getContributionHtml(obj, scRoutingContext.url)
|
|
405
|
-
} })) : (React.createElement(Typography, { component: "div", gutterBottom: true, className: classes.text },
|
|
406
|
-
React.createElement(Typography, { component: "span", dangerouslySetInnerHTML: { __html: expanded ? getContributionHtml(obj, scRoutingContext.url) : obj.summary } }),
|
|
407
|
-
!expanded && obj.html.length >= MAX_SUMMARY_LENGTH && (React.createElement(Button, { size: "small", variant: "text", color: "inherit", onClick: () => setExpanded(!expanded) },
|
|
408
|
-
React.createElement(FormattedMessage, { id: "ui.feedObject.content.showMore", defaultMessage: "ui.feedObject.content.showMore" })))))),
|
|
442
|
+
React.createElement(Box, { className: classes.textSection }, getContributionSummary(obj, template)),
|
|
409
443
|
React.createElement(Box, { className: classes.mediasSection },
|
|
410
444
|
React.createElement(MediasPreview, Object.assign({ medias: obj.medias }, MediasPreviewProps))),
|
|
411
445
|
React.createElement(Box, { className: classes.pollsSection }, obj['poll'] && (React.createElement(PollObject, Object.assign({ visible: pollVisible ||
|
|
@@ -438,11 +472,7 @@ export default function FeedObject(inProps) {
|
|
|
438
472
|
React.createElement(CardContent, { classes: { root: classes.content } },
|
|
439
473
|
React.createElement(Box, { className: classes.titleSection }, 'title' in obj && (React.createElement(Link, { to: scRoutingContext.url(getContributionRouteName(obj), getRouteData(obj)) },
|
|
440
474
|
React.createElement(Typography, { variant: "body1", gutterBottom: true, className: classes.title }, obj.title)))),
|
|
441
|
-
React.createElement(Box, { className: classes.textSection },
|
|
442
|
-
React.createElement(Link, { to: scRoutingContext.url(getContributionRouteName(obj), getRouteData(obj)), className: classes.text },
|
|
443
|
-
React.createElement(Typography, { component: "div", className: classes.text, variant: "body2", gutterBottom: true, dangerouslySetInnerHTML: { __html: expanded ? getContributionHtml(obj, scRoutingContext.url) : obj.summary } })),
|
|
444
|
-
!expanded && obj.html.length >= MAX_SUMMARY_LENGTH && (React.createElement(Button, { size: "small", variant: "text", color: "inherit", onClick: () => setExpanded(!expanded) },
|
|
445
|
-
React.createElement(FormattedMessage, { id: "ui.feedObject.content.showMore", defaultMessage: "ui.feedObject.content.showMore" })))),
|
|
475
|
+
React.createElement(Box, { className: classes.textSection }, getContributionSummary(obj, template)),
|
|
446
476
|
React.createElement(Box, { className: classes.mediasSection },
|
|
447
477
|
React.createElement(MediasPreview, Object.assign({ medias: obj.medias }, MediasPreviewProps))),
|
|
448
478
|
React.createElement(Box, { className: classes.pollsSection }, obj['poll'] && (React.createElement(PollObject, Object.assign({ feedObject: obj, pollObject: obj['poll'], onChange: handleChangePoll, visible: Boolean(obj.type !== SCContributionType.DISCUSSION && !obj.html && !obj.medias.length) }, PollObjectProps))))))) : (React.createElement(FeedObjectSkeleton, Object.assign({ template: template }, FeedObjectSkeletonProps)))));
|
|
@@ -17,10 +17,10 @@ export declare function getContributionSnippet(obj: any): any;
|
|
|
17
17
|
/**
|
|
18
18
|
* Get the contribution text
|
|
19
19
|
* Hydrate text with mention, etc.
|
|
20
|
-
* @param
|
|
20
|
+
* @param html Html of the contribution
|
|
21
21
|
* @param handleUrl Func that handle urls
|
|
22
22
|
*/
|
|
23
|
-
export declare function getContributionHtml(
|
|
23
|
+
export declare function getContributionHtml(html: any, handleUrl: any): any;
|
|
24
24
|
/**
|
|
25
25
|
* Get route name for a contribution
|
|
26
26
|
* @param obj
|
|
@@ -47,11 +47,11 @@ export function getContributionSnippet(obj) {
|
|
|
47
47
|
/**
|
|
48
48
|
* Get the contribution text
|
|
49
49
|
* Hydrate text with mention, etc.
|
|
50
|
-
* @param
|
|
50
|
+
* @param html Html of the contribution
|
|
51
51
|
* @param handleUrl Func that handle urls
|
|
52
52
|
*/
|
|
53
|
-
export function getContributionHtml(
|
|
54
|
-
return
|
|
53
|
+
export function getContributionHtml(html, handleUrl) {
|
|
54
|
+
return html.replace(/<mention.*? id="([0-9]+)"{1}.*?>@([a-z\d_]+)<\/mention>/gi, (match, id, username) => {
|
|
55
55
|
return `<a href='${handleUrl(SCRoutes.USER_PROFILE_ROUTE_NAME, { id, username })}'>@${username}</a>`;
|
|
56
56
|
});
|
|
57
57
|
}
|