@reltio/components 1.4.1164 → 1.4.1165

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/cjs/components/CollaborationItem/CollaborationItem.js +3 -10
  2. package/cjs/components/CollaborationItem/Comment/Comment.d.ts +3 -2
  3. package/cjs/components/CollaborationItem/Comment/Comment.js +24 -14
  4. package/cjs/components/CollaborationItem/Comment/styles.d.ts +1 -1
  5. package/cjs/components/CollaborationItem/RepliedComment/RepliedComment.d.ts +7 -4
  6. package/cjs/components/CollaborationItem/RepliedComment/RepliedComment.js +57 -5
  7. package/cjs/components/CollaborationItem/SendMessageArea/SendMessageArea.d.ts +6 -4
  8. package/cjs/components/CollaborationItem/SendMessageArea/SendMessageArea.js +30 -12
  9. package/cjs/components/CollaborationItem/SendMessageArea/styles.d.ts +5 -1
  10. package/cjs/components/CollaborationItem/SendMessageArea/styles.js +15 -9
  11. package/cjs/components/CollaborationItem/TextFieldWithMentions/styles.js +1 -3
  12. package/cjs/contexts/CollaborationContext/index.d.ts +8 -0
  13. package/cjs/contexts/CollaborationContext/index.js +3 -1
  14. package/cjs/hooks/useCollaboration.d.ts +2 -0
  15. package/cjs/hooks/useCollaboration.js +57 -5
  16. package/esm/components/CollaborationItem/CollaborationItem.js +4 -11
  17. package/esm/components/CollaborationItem/Comment/Comment.d.ts +3 -2
  18. package/esm/components/CollaborationItem/Comment/Comment.js +25 -15
  19. package/esm/components/CollaborationItem/Comment/styles.d.ts +1 -1
  20. package/esm/components/CollaborationItem/RepliedComment/RepliedComment.d.ts +7 -4
  21. package/esm/components/CollaborationItem/RepliedComment/RepliedComment.js +38 -5
  22. package/esm/components/CollaborationItem/SendMessageArea/SendMessageArea.d.ts +6 -4
  23. package/esm/components/CollaborationItem/SendMessageArea/SendMessageArea.js +30 -12
  24. package/esm/components/CollaborationItem/SendMessageArea/styles.d.ts +5 -1
  25. package/esm/components/CollaborationItem/SendMessageArea/styles.js +15 -9
  26. package/esm/components/CollaborationItem/TextFieldWithMentions/styles.js +1 -3
  27. package/esm/contexts/CollaborationContext/index.d.ts +8 -0
  28. package/esm/contexts/CollaborationContext/index.js +3 -1
  29. package/esm/hooks/useCollaboration.d.ts +2 -0
  30. package/esm/hooks/useCollaboration.js +58 -6
  31. package/package.json +3 -3
@@ -33,22 +33,15 @@ exports.CollaborationItem = react_1.memo(function (_a) {
33
33
  var uri = _a.uri, relatedObjectUris = _a.relatedObjectUris, objectType = _a.objectType, classes = _a.classes, popperRef = _a.popperRef, messagesRef = _a.messagesRef, comment = _a.comment;
34
34
  var inputRef = react_1.useRef();
35
35
  var styles = styles_1.useStyles({ classes: classes });
36
- var _b = react_1.useState(false), isEditingComment = _b[0], setIsEditingComment = _b[1];
37
36
  var handleReply = function () {
38
- if (isEditingComment) {
39
- setIsEditingComment(false);
40
- }
41
37
  inputRef.current.focus();
42
38
  };
43
- var handleSetEdit = function () {
44
- setIsEditingComment(true);
45
- };
46
- var sendMessageArea = (react_1.default.createElement(SendMessageArea_1.SendMessageArea, { className: styles.sendMessageArea, inputRef: inputRef, popperRef: popperRef, uri: uri, relatedObjectUris: relatedObjectUris, objectType: objectType, comment: comment, onCancel: function () { return setIsEditingComment(false); }, isEditingComment: isEditingComment }));
39
+ var sendMessageArea = (react_1.default.createElement(SendMessageArea_1.SendMessageArea, { className: styles.sendMessageArea, inputRef: inputRef, popperRef: popperRef, uri: uri, relatedObjectUris: relatedObjectUris, objectType: objectType, comment: comment }));
47
40
  return (react_1.default.createElement(Box_1.default, { className: styles.root },
48
41
  comment && (react_1.default.createElement(react_1.default.Fragment, null,
49
42
  react_1.default.createElement("div", { className: styles.messages, ref: messagesRef },
50
- react_1.default.createElement(Comment_1.Comment, { comment: comment, uri: uri, onReply: handleReply, onStartEditing: handleSetEdit, className: styles.comment }),
51
- react_1.default.createElement(Box_1.default, { className: styles.replies }, comment.replies.map(function (reply) { return (react_1.default.createElement(RepliedComment_1.RepliedComment, { key: reply.replyId, className: styles.repliedComment, reply: reply })); }))),
43
+ react_1.default.createElement(Comment_1.Comment, { comment: comment, uri: uri, onReply: handleReply, className: styles.comment, relatedObjectUris: relatedObjectUris, objectType: objectType }),
44
+ react_1.default.createElement(Box_1.default, { className: styles.replies }, comment.replies.map(function (reply) { return (react_1.default.createElement(RepliedComment_1.RepliedComment, { key: reply.replyId, className: styles.repliedComment, reply: reply, uri: uri, comment: comment })); }))),
52
45
  sendMessageArea)),
53
46
  !comment && sendMessageArea));
54
47
  });
@@ -5,7 +5,8 @@ declare type Props = {
5
5
  onReply: () => void;
6
6
  className?: string;
7
7
  comment: CommentType;
8
- onStartEditing: () => void;
8
+ relatedObjectUris: CommentType['relatedObjectUris'];
9
+ objectType: CommentType['objectType'];
9
10
  };
10
- export declare const Comment: ({ onReply, className, uri, comment, onStartEditing }: Props) => JSX.Element;
11
+ export declare const Comment: ({ onReply, className, uri, comment, relatedObjectUris, objectType }: Props) => JSX.Element;
11
12
  export {};
@@ -24,11 +24,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
24
24
  Object.defineProperty(exports, "__esModule", { value: true });
25
25
  exports.Comment = void 0;
26
26
  var react_1 = __importStar(require("react"));
27
+ var react_redux_1 = require("react-redux");
27
28
  var ui_i18n_1 = __importDefault(require("ui-i18n"));
28
29
  var Link_1 = __importDefault(require("@material-ui/core/Link"));
29
30
  var Box_1 = __importDefault(require("@material-ui/core/Box"));
30
31
  var Typography_1 = __importDefault(require("@material-ui/core/Typography"));
31
32
  var MoreVert_1 = __importDefault(require("@material-ui/icons/MoreVert"));
33
+ var mdm_module_1 = __importDefault(require("@reltio/mdm-module"));
32
34
  var DropDownMenuButton_1 = __importDefault(require("../../DropDownMenuButton/DropDownMenuButton"));
33
35
  var SmallIconButton_1 = require("../../SmallIconButton");
34
36
  var CommentTarget_1 = require("../CommentTarget/CommentTarget");
@@ -36,44 +38,52 @@ var CommentContent_1 = require("../CommentContent/CommentContent");
36
38
  var Avatar_1 = require("../Avatar/Avatar");
37
39
  var contexts_1 = require("../../../contexts");
38
40
  var utils_1 = require("../utils");
41
+ var SendMessageArea_1 = require("../SendMessageArea/SendMessageArea");
39
42
  var styles_1 = require("./styles");
40
- var react_redux_1 = require("react-redux");
41
- var mdm_module_1 = __importDefault(require("@reltio/mdm-module"));
42
43
  var Comment = function (_a) {
43
- var onReply = _a.onReply, className = _a.className, uri = _a.uri, comment = _a.comment, onStartEditing = _a.onStartEditing;
44
+ var onReply = _a.onReply, className = _a.className, uri = _a.uri, comment = _a.comment, relatedObjectUris = _a.relatedObjectUris, objectType = _a.objectType;
44
45
  var styles = styles_1.useStyles();
46
+ var inputRef = react_1.useRef();
47
+ var _b = react_1.useState(false), isEditingComment = _b[0], setIsEditingComment = _b[1];
45
48
  var username = react_redux_1.useSelector(mdm_module_1.default.selectors.getUserName);
46
- var canChangeComment = comment.createdBy === username;
47
- var _b = react_1.useContext(contexts_1.CollaborationContext), resolveThread = _b.resolveThread, reOpenThread = _b.reOpenThread, sending = _b.sending, deleteComment = _b.deleteComment;
49
+ var commentId = comment.commentId, createdBy = comment.createdBy, createdTime = comment.createdTime;
50
+ var canChangeComment = createdBy === username;
51
+ var _c = react_1.useContext(contexts_1.CollaborationContext), resolveThread = _c.resolveThread, reOpenThread = _c.reOpenThread, sending = _c.sending, deleteComment = _c.deleteComment;
52
+ react_1.useEffect(function () {
53
+ if (isEditingComment) {
54
+ inputRef.current.focus();
55
+ }
56
+ }, [isEditingComment]);
48
57
  var menuItems = react_1.useMemo(function () { return [
49
58
  {
50
59
  text: ui_i18n_1.default.text('Edit'),
51
- onClick: onStartEditing
60
+ onClick: function () { return setIsEditingComment(true); }
52
61
  },
53
62
  {
54
63
  text: ui_i18n_1.default.text('Delete'),
55
- onClick: function () { return deleteComment({ uri: uri, commentId: comment.commentId }); }
64
+ onClick: function () { return deleteComment({ uri: uri, commentId: commentId }); }
56
65
  }
57
- ]; }, [onStartEditing, deleteComment, uri, comment]);
66
+ ]; }, [deleteComment, uri, commentId]);
58
67
  var handleResolve = function () {
59
- resolveThread({ commentId: comment.commentId, uri: uri });
68
+ resolveThread({ commentId: commentId, uri: uri });
60
69
  };
61
70
  var handleReOpen = function () {
62
- reOpenThread({ commentId: comment.commentId, uri: uri });
71
+ reOpenThread({ commentId: commentId, uri: uri });
63
72
  };
73
+ var sendMessageArea = (react_1.default.createElement(SendMessageArea_1.SendMessageArea, { inputRef: inputRef, uri: uri, relatedObjectUris: relatedObjectUris, objectType: objectType, onCancel: function () { return setIsEditingComment(false); }, isEditingComment: isEditingComment, comment: comment }));
64
74
  return (react_1.default.createElement(Box_1.default, { className: className },
65
75
  react_1.default.createElement(Box_1.default, { className: styles.header },
66
- react_1.default.createElement(Avatar_1.Avatar, { classes: { root: styles.avatar } }, comment.createdBy),
76
+ react_1.default.createElement(Avatar_1.Avatar, { classes: { root: styles.avatar } }, createdBy),
67
77
  react_1.default.createElement(Box_1.default, { width: "100%" },
68
- react_1.default.createElement(Typography_1.default, { className: styles.username }, comment.createdBy)),
69
- react_1.default.createElement(Typography_1.default, { className: styles.createdAt }, utils_1.formatDate(comment.createdTime)),
78
+ react_1.default.createElement(Typography_1.default, { className: styles.username }, createdBy)),
79
+ react_1.default.createElement(Typography_1.default, { className: styles.createdAt }, utils_1.formatDate(createdTime)),
70
80
  canChangeComment && (react_1.default.createElement(DropDownMenuButton_1.default, { buttonComponent: SmallIconButton_1.SmallIconButtonWithTooltip, buttonProps: {
71
81
  icon: MoreVert_1.default,
72
82
  tooltipTitle: ui_i18n_1.default.text('Open menu')
73
83
  }, popoverProps: { PopoverClasses: { root: styles.dropdownMenu } }, menuItems: menuItems, menuId: "collaboration-comment-menu" }))),
74
84
  react_1.default.createElement(Box_1.default, { className: styles.body },
75
85
  react_1.default.createElement(CommentTarget_1.CommentTarget, { comment: comment, className: styles.commentTarget }),
76
- react_1.default.createElement(CommentContent_1.CommentContent, { comment: comment, className: styles.message }),
86
+ isEditingComment ? sendMessageArea : react_1.default.createElement(CommentContent_1.CommentContent, { comment: comment, className: styles.message }),
77
87
  react_1.default.createElement(Box_1.default, { className: styles.buttons },
78
88
  react_1.default.createElement(Link_1.default, { className: styles.button, onClick: onReply, component: "button" }, ui_i18n_1.default.text('Reply')),
79
89
  comment.status === 'open' && (react_1.default.createElement(Link_1.default, { disabled: sending, className: styles.button, onClick: handleResolve, component: "button" }, ui_i18n_1.default.text('Resolve'))),
@@ -1 +1 @@
1
- export declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"body" | "message" | "button" | "header" | "avatar" | "username" | "createdAt" | "commentTarget" | "dropdownMenu" | "buttons">;
1
+ export declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"body" | "message" | "button" | "header" | "avatar" | "username" | "buttons" | "createdAt" | "commentTarget" | "dropdownMenu">;
@@ -1,8 +1,11 @@
1
- /// <reference types="react" />
2
- import { Reply } from '@reltio/mdm-sdk';
1
+ import React from 'react';
2
+ import { Reply, Comment as CommentType } from '@reltio/mdm-sdk';
3
3
  declare type Props = {
4
4
  className?: string;
5
- reply: Pick<Reply, 'createdTime' | 'content' | 'createdBy' | 'action' | 'namedUsers'>;
5
+ reply: Pick<Reply, 'createdTime' | 'content' | 'createdBy' | 'action' | 'namedUsers' | 'replyId'>;
6
+ comment?: CommentType;
7
+ uri: string;
8
+ popperRef?: React.RefObject<any>;
6
9
  };
7
- export declare const RepliedComment: ({ className, reply }: Props) => JSX.Element;
10
+ export declare const RepliedComment: ({ className, reply, uri, comment, popperRef }: Props) => JSX.Element;
8
11
  export {};
@@ -1,30 +1,82 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
11
+ }) : function(o, v) {
12
+ o["default"] = v;
13
+ });
14
+ var __importStar = (this && this.__importStar) || function (mod) {
15
+ if (mod && mod.__esModule) return mod;
16
+ var result = {};
17
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
+ __setModuleDefault(result, mod);
19
+ return result;
20
+ };
2
21
  var __importDefault = (this && this.__importDefault) || function (mod) {
3
22
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
23
  };
5
24
  Object.defineProperty(exports, "__esModule", { value: true });
6
25
  exports.RepliedComment = void 0;
7
- var react_1 = __importDefault(require("react"));
26
+ var react_1 = __importStar(require("react"));
27
+ var react_redux_1 = require("react-redux");
8
28
  var ui_i18n_1 = __importDefault(require("ui-i18n"));
9
29
  var classnames_1 = __importDefault(require("classnames"));
30
+ var mdm_module_1 = __importDefault(require("@reltio/mdm-module"));
10
31
  var Box_1 = __importDefault(require("@material-ui/core/Box"));
32
+ var MoreVert_1 = __importDefault(require("@material-ui/icons/MoreVert"));
11
33
  var Typography_1 = __importDefault(require("@material-ui/core/Typography"));
12
34
  var Avatar_1 = require("../Avatar/Avatar");
13
35
  var CommentContent_1 = require("../CommentContent/CommentContent");
14
36
  var utils_1 = require("../utils");
15
37
  var styles_1 = require("./styles");
38
+ var contexts_1 = require("../../../contexts");
39
+ var DropDownMenuButton_1 = __importDefault(require("../../DropDownMenuButton/DropDownMenuButton"));
40
+ var SmallIconButton_1 = require("../../SmallIconButton");
41
+ var SendMessageArea_1 = require("../SendMessageArea/SendMessageArea");
16
42
  var RepliedComment = function (_a) {
17
- var className = _a.className, reply = _a.reply;
43
+ var className = _a.className, reply = _a.reply, uri = _a.uri, comment = _a.comment, popperRef = _a.popperRef;
44
+ var inputRef = react_1.useRef();
45
+ var _b = react_1.useState(false), isEditingReply = _b[0], setIsEditingReply = _b[1];
18
46
  var createdBy = reply.createdBy, action = reply.action, createdTime = reply.createdTime;
47
+ var username = react_redux_1.useSelector(mdm_module_1.default.selectors.getUserName);
48
+ var canChangeReply = createdBy === username;
49
+ var deleteReply = react_1.useContext(contexts_1.CollaborationContext).deleteReply;
50
+ react_1.useEffect(function () {
51
+ if (isEditingReply) {
52
+ inputRef.current.focus();
53
+ }
54
+ }, [isEditingReply]);
19
55
  var styles = styles_1.useStyles();
56
+ var menuItems = react_1.useMemo(function () { return [
57
+ {
58
+ text: ui_i18n_1.default.text('Edit'),
59
+ onClick: function () { return setIsEditingReply(true); }
60
+ },
61
+ {
62
+ text: ui_i18n_1.default.text('Delete'),
63
+ onClick: function () { return deleteReply({ uri: uri, commentId: comment.commentId, reply: reply }); }
64
+ }
65
+ ]; }, [deleteReply, uri, comment.commentId, reply]);
66
+ var sendMessageArea = (react_1.default.createElement(SendMessageArea_1.SendMessageArea, { inputRef: inputRef, popperRef: popperRef, uri: uri, onCancel: function () { return setIsEditingReply(false); }, isEditingReply: isEditingReply, reply: reply, comment: comment }));
20
67
  return (react_1.default.createElement(Box_1.default, { className: classnames_1.default(styles.root, className) },
21
68
  react_1.default.createElement(Avatar_1.Avatar, { classes: { root: styles.avatar } }, createdBy),
22
- react_1.default.createElement(Box_1.default, null,
69
+ react_1.default.createElement(Box_1.default, { flexGrow: 1 },
23
70
  react_1.default.createElement(Box_1.default, { className: styles.header },
24
71
  react_1.default.createElement(Typography_1.default, { className: styles.username }, createdBy),
25
72
  action === 'resolve' && (react_1.default.createElement(Typography_1.default, { className: styles.marked }, ui_i18n_1.default.text('Marked as resolved'))),
26
73
  action === 'reopen' && react_1.default.createElement(Typography_1.default, { className: styles.marked }, ui_i18n_1.default.text('Re-opened'))),
27
- action !== 'resolve' && react_1.default.createElement(CommentContent_1.CommentContent, { className: styles.message, comment: reply }),
28
- react_1.default.createElement(Typography_1.default, { className: styles.createdAt }, utils_1.formatDate(createdTime)))));
74
+ action !== 'resolve' &&
75
+ (isEditingReply ? sendMessageArea : react_1.default.createElement(CommentContent_1.CommentContent, { className: styles.message, comment: reply })),
76
+ react_1.default.createElement(Typography_1.default, { className: styles.createdAt }, utils_1.formatDate(createdTime))),
77
+ canChangeReply && (react_1.default.createElement(DropDownMenuButton_1.default, { buttonComponent: SmallIconButton_1.SmallIconButtonWithTooltip, buttonProps: {
78
+ icon: MoreVert_1.default,
79
+ tooltipTitle: ui_i18n_1.default.text('Open menu')
80
+ }, menuItems: menuItems, menuId: "collaboration-comment-menu" }))));
29
81
  };
30
82
  exports.RepliedComment = RepliedComment;
@@ -1,15 +1,17 @@
1
1
  import React from 'react';
2
- import { Comment } from '@reltio/mdm-sdk';
2
+ import { Comment, Reply } from '@reltio/mdm-sdk';
3
3
  declare type Props = {
4
4
  inputRef: React.RefObject<HTMLInputElement>;
5
5
  className?: string;
6
6
  uri: string;
7
- objectType: Comment['objectType'];
8
- relatedObjectUris: Comment['relatedObjectUris'];
7
+ objectType?: Comment['objectType'];
8
+ relatedObjectUris?: Comment['relatedObjectUris'];
9
9
  popperRef?: React.RefObject<any>;
10
10
  comment?: Comment;
11
+ reply?: Pick<Reply, 'content' | 'replyId'>;
11
12
  isEditingComment?: boolean;
13
+ isEditingReply?: boolean;
12
14
  onCancel?: () => void;
13
15
  };
14
- export declare const SendMessageArea: ({ inputRef, className, uri, relatedObjectUris, objectType, popperRef, comment, isEditingComment, onCancel }: Props) => JSX.Element;
16
+ export declare const SendMessageArea: ({ inputRef, className, uri, relatedObjectUris, objectType, popperRef, comment, reply, isEditingComment, isEditingReply, onCancel }: Props) => JSX.Element;
15
17
  export {};
@@ -27,6 +27,7 @@ var react_1 = __importStar(require("react"));
27
27
  var ui_i18n_1 = __importDefault(require("ui-i18n"));
28
28
  var classnames_1 = __importDefault(require("classnames"));
29
29
  var react_redux_1 = require("react-redux");
30
+ var ramda_1 = require("ramda");
30
31
  var mdm_module_1 = __importDefault(require("@reltio/mdm-module"));
31
32
  var Box_1 = __importDefault(require("@material-ui/core/Box"));
32
33
  var Button_1 = __importDefault(require("@material-ui/core/Button"));
@@ -34,7 +35,6 @@ var TextFieldWithMentions_1 = require("../TextFieldWithMentions/TextFieldWithMen
34
35
  var Avatar_1 = require("../Avatar/Avatar");
35
36
  var contexts_1 = require("../../../contexts");
36
37
  var styles_1 = require("./styles");
37
- var ramda_1 = require("ramda");
38
38
  var hooks_1 = require("../../../hooks");
39
39
  var getPlaceholder = function (status) {
40
40
  switch (status) {
@@ -46,8 +46,8 @@ var getPlaceholder = function (status) {
46
46
  return '';
47
47
  }
48
48
  };
49
- var getButtonText = function (status, isEditingComment) {
50
- if (isEditingComment) {
49
+ var getButtonText = function (status, isEditingComment, isEditingReply) {
50
+ if (isEditingComment || isEditingReply) {
51
51
  return ui_i18n_1.default.text('Edit');
52
52
  }
53
53
  if (status === 'open' || status === 'resolved') {
@@ -56,10 +56,11 @@ var getButtonText = function (status, isEditingComment) {
56
56
  return ui_i18n_1.default.text('Comment');
57
57
  };
58
58
  var SendMessageArea = function (_a) {
59
- var inputRef = _a.inputRef, className = _a.className, uri = _a.uri, relatedObjectUris = _a.relatedObjectUris, objectType = _a.objectType, popperRef = _a.popperRef, comment = _a.comment, isEditingComment = _a.isEditingComment, onCancel = _a.onCancel;
60
- var styles = styles_1.useStyles();
59
+ var inputRef = _a.inputRef, className = _a.className, uri = _a.uri, relatedObjectUris = _a.relatedObjectUris, objectType = _a.objectType, popperRef = _a.popperRef, comment = _a.comment, reply = _a.reply, isEditingComment = _a.isEditingComment, isEditingReply = _a.isEditingReply, onCancel = _a.onCancel;
60
+ var isEditing = isEditingComment || isEditingReply;
61
+ var styles = styles_1.useStyles({ isEditing: isEditing });
61
62
  var username = react_redux_1.useSelector(mdm_module_1.default.selectors.getUserName);
62
- var _b = react_1.useContext(contexts_1.CollaborationContext), createReply = _b.createReply, createComment = _b.createComment, sending = _b.sending, editComment = _b.editComment;
63
+ var _b = react_1.useContext(contexts_1.CollaborationContext), createReply = _b.createReply, createComment = _b.createComment, sending = _b.sending, editComment = _b.editComment, editReply = _b.editReply;
63
64
  var _c = react_1.useState(''), value = _c[0], setValue = _c[1];
64
65
  var _d = react_1.useState(''), plainTextValue = _d[0], setPlainTextValue = _d[1];
65
66
  var _e = react_1.useState([]), mentions = _e[0], setMentions = _e[1];
@@ -112,6 +113,17 @@ var SendMessageArea = function (_a) {
112
113
  });
113
114
  }
114
115
  ],
116
+ [
117
+ ramda_1.always(isEditingReply),
118
+ function () {
119
+ return editReply({
120
+ content: plainTextValue,
121
+ namedUsers: mentions,
122
+ commentId: comment.commentId,
123
+ replyId: reply.replyId
124
+ });
125
+ }
126
+ ],
115
127
  [
116
128
  ramda_1.T,
117
129
  function () {
@@ -133,20 +145,26 @@ var SendMessageArea = function (_a) {
133
145
  }
134
146
  }, [popperRef, shouldShowButtons]);
135
147
  react_1.useEffect(function () {
136
- if (isEditingComment) {
137
- setValue(comment.content);
148
+ if (isEditingComment || isEditingReply) {
149
+ if (isEditingComment) {
150
+ setValue(comment.content);
151
+ }
152
+ else {
153
+ setValue(reply.content);
154
+ }
138
155
  }
139
156
  else {
140
157
  clearValue();
141
158
  }
142
- }, [isEditingComment]);
159
+ }, [isEditingComment, isEditingReply]);
160
+ var buttonSize = isEditing ? 'small' : 'medium';
143
161
  return (react_1.default.createElement(Box_1.default, { className: classnames_1.default(styles.root, className) },
144
162
  react_1.default.createElement("form", { onSubmit: handleSubmit, className: styles.form },
145
163
  react_1.default.createElement(Box_1.default, { className: styles.main },
146
- react_1.default.createElement(Avatar_1.Avatar, { classes: { root: styles.avatar } }, username),
164
+ !isEditing && react_1.default.createElement(Avatar_1.Avatar, { classes: { root: styles.avatar } }, username),
147
165
  react_1.default.createElement(TextFieldWithMentions_1.TextFieldWithMentions, { className: styles.textField, disabled: sending, onChange: handleChange, inputRef: inputRef, value: value, onFocus: handleFocus, onBlur: handleBlur, placeholder: getPlaceholder(status) })),
148
166
  shouldShowButtons && (react_1.default.createElement(Box_1.default, { className: styles.buttons },
149
- react_1.default.createElement(Button_1.default, { className: styles.button, variant: "contained", color: "primary", disabled: !hasValue || sending, type: "submit" }, getButtonText(status, isEditingComment)),
150
- react_1.default.createElement(Button_1.default, { disabled: sending, onClick: handleCancel, className: styles.button, variant: "outlined", color: "primary" }, ui_i18n_1.default.text('Cancel')))))));
167
+ react_1.default.createElement(Button_1.default, { className: styles.button, variant: "contained", color: "primary", disabled: !hasValue || sending, type: "submit", size: buttonSize }, getButtonText(status, isEditingComment, isEditingReply)),
168
+ react_1.default.createElement(Button_1.default, { disabled: sending, onClick: handleCancel, className: styles.button, variant: "outlined", color: "primary", size: buttonSize }, ui_i18n_1.default.text('Cancel')))))));
151
169
  };
152
170
  exports.SendMessageArea = SendMessageArea;
@@ -1 +1,5 @@
1
- export declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"button" | "form" | "main" | "root" | "avatar" | "buttons" | "textField">;
1
+ declare type StylesProps = {
2
+ isEditing?: boolean;
3
+ };
4
+ export declare const useStyles: (props: StylesProps) => import("@material-ui/core/styles/withStyles").ClassNameMap<"button" | "form" | "main" | "root" | "avatar" | "textField" | "buttons">;
5
+ export {};
@@ -3,13 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useStyles = void 0;
4
4
  var styles_1 = require("@material-ui/core/styles");
5
5
  exports.useStyles = styles_1.makeStyles({
6
- root: {
7
- padding: '6px 6px 6px 8px',
8
- borderRadius: '4px',
9
- backgroundColor: 'rgba(0,114,206,0.06)'
6
+ root: function (_a) {
7
+ var isEditing = _a.isEditing;
8
+ return ({
9
+ padding: isEditing ? '6px 6px 6px 0' : ' 6px 6px 6px 8px',
10
+ borderRadius: '4px',
11
+ backgroundColor: isEditing ? 'transparent' : 'rgba(0,114,206,0.06)'
12
+ });
10
13
  },
11
- textField: {
12
- maxWidth: 'calc(100% - 40px)'
14
+ textField: function (_a) {
15
+ var isEditing = _a.isEditing;
16
+ return ({
17
+ maxWidth: isEditing ? '100%' : 'calc(100% - 40px)'
18
+ });
13
19
  },
14
20
  form: {
15
21
  marginBottom: 0
@@ -21,9 +27,9 @@ exports.useStyles = styles_1.makeStyles({
21
27
  avatar: {
22
28
  marginRight: '8px'
23
29
  },
24
- buttons: {
25
- marginLeft: '40px',
26
- marginTop: '8px'
30
+ buttons: function (_a) {
31
+ var isEditing = _a.isEditing;
32
+ return ({ marginLeft: isEditing ? '0' : '40px', marginTop: '8px' });
27
33
  },
28
34
  button: {
29
35
  '& + $button': {
@@ -12,15 +12,13 @@ exports.useStyles = styles_1.makeStyles(function (theme) { return ({
12
12
  },
13
13
  '&__highlighter': {
14
14
  padding: '10px 22px',
15
- border: '1px solid transparent !important',
16
- maxHeight: '70px'
15
+ border: '1px solid transparent !important'
17
16
  },
18
17
  '&__input': {
19
18
  borderRadius: '2px',
20
19
  border: '1px solid rgba(0,0,0,0.12)',
21
20
  padding: '10px 22px',
22
21
  outline: 0,
23
- maxHeight: '70px',
24
22
  overflow: 'auto !important'
25
23
  },
26
24
  '&__suggestions': {
@@ -14,9 +14,17 @@ export declare const CollaborationContext: React.Context<{
14
14
  editComment: (params: Pick<Comment, 'content' | 'namedUsers' | 'objectType' | 'relatedObjectUris' | 'commentId' | 'replies'> & {
15
15
  uri: string;
16
16
  }) => Promise<void>;
17
+ editReply: (params: Pick<Reply, 'content' | 'namedUsers' | 'replyId'> & {
18
+ commentId: string;
19
+ }) => Promise<void>;
17
20
  deleteComment: (params: Pick<Comment, 'commentId'> & {
18
21
  uri: string;
19
22
  }) => void;
23
+ deleteReply: (params: {
24
+ uri: string;
25
+ commentId: string;
26
+ reply: Pick<Reply, 'action' | 'replyId'>;
27
+ }) => void;
20
28
  createReply: (params: Pick<Reply, 'content' | 'namedUsers' | 'action'> & {
21
29
  uri: string;
22
30
  commentId: string;
@@ -22,6 +22,8 @@ exports.CollaborationContext = react_1.default.createContext({
22
22
  deleteComment: noop,
23
23
  sending: false,
24
24
  loading: false,
25
- pageToken: null
25
+ pageToken: null,
26
+ deleteReply: noop,
27
+ editReply: function () { return new Promise(noop); }
26
28
  });
27
29
  exports.CollaborationContext.displayName = 'CollaborationContext';
@@ -22,5 +22,7 @@ export declare const useCollaboration: ({ objectIds, objectTypes, enabled }: Pro
22
22
  reOpenThread: ({ commentId, uri }: any) => void;
23
23
  resolveThread: ({ commentId, uri }: any) => void;
24
24
  sending: boolean;
25
+ deleteReply: ({ uri, commentId, reply }: any) => void;
26
+ editReply: ({ content, namedUsers, commentId, replyId }: any) => Promise<void>;
25
27
  };
26
28
  export {};
@@ -25,6 +25,16 @@ var react_redux_1 = require("react-redux");
25
25
  var ramda_1 = require("ramda");
26
26
  var mdm_sdk_1 = require("@reltio/mdm-sdk");
27
27
  var mdm_module_1 = __importDefault(require("@reltio/mdm-module"));
28
+ var filterReplies = function (replyId, replies) { return replies.filter(function (reply) { return reply.replyId !== replyId; }); };
29
+ var getUpdatedReplies = function (comment, reply) {
30
+ var changedReplyIndex = comment.replies.findIndex(function (_a) {
31
+ var replyId = _a.replyId;
32
+ return replyId === reply.replyId;
33
+ });
34
+ var newReplies = __spreadArray([], comment.replies);
35
+ newReplies[changedReplyIndex] = reply;
36
+ return newReplies;
37
+ };
28
38
  var defaultObjectIds = [];
29
39
  var catchErrorInRequest = function (e) { return console.error('Collaboration error', e); };
30
40
  var useCollaboration = function (_a) {
@@ -150,8 +160,9 @@ var useCollaboration = function (_a) {
150
160
  .catch(catchErrorInRequest)
151
161
  .finally(function () { return setSending(false); });
152
162
  }, [collaborationPath, tenant]);
153
- var updateReplyInState = react_1.useCallback(function (reply, uri, commentId) {
163
+ var updateReplyInState = react_1.useCallback(function (reply, uri, commentId, isDeleteReply) {
154
164
  var newStatus = reply.action === 'resolve' ? 'resolved' : 'open';
165
+ var replyId = reply.replyId;
155
166
  if (newStatus === 'resolved') {
156
167
  setCurrentComment(function (prevCurrentComment) {
157
168
  if (prevCurrentComment) {
@@ -162,7 +173,9 @@ var useCollaboration = function (_a) {
162
173
  else {
163
174
  setCurrentComment(function (prevCurrentComment) {
164
175
  if (prevCurrentComment) {
165
- return __assign(__assign({}, prevCurrentComment), { replies: __spreadArray(__spreadArray([], prevCurrentComment.replies), [reply]) });
176
+ return __assign(__assign({}, prevCurrentComment), { replies: isDeleteReply
177
+ ? filterReplies(replyId, prevCurrentComment.replies)
178
+ : __spreadArray(__spreadArray([], prevCurrentComment.replies), [reply]) });
166
179
  }
167
180
  });
168
181
  }
@@ -170,7 +183,7 @@ var useCollaboration = function (_a) {
170
183
  var _a;
171
184
  return (__assign(__assign({}, prevCommentsMap), (_a = {}, _a[uri] = (prevCommentsMap[uri] || []).map(function (comment) {
172
185
  if (comment.commentId === commentId) {
173
- return __assign(__assign({}, comment), { status: newStatus, replies: comment.replies + 1 });
186
+ return __assign(__assign({}, comment), { status: newStatus, replies: isDeleteReply ? comment.replies - 1 : comment.replies + 1 });
174
187
  }
175
188
  return comment;
176
189
  }), _a)));
@@ -178,12 +191,49 @@ var useCollaboration = function (_a) {
178
191
  setComments(function (prevComments) {
179
192
  return prevComments.map(function (comment) {
180
193
  if (comment.commentId === commentId) {
181
- return __assign(__assign({}, comment), { status: newStatus, replies: __spreadArray(__spreadArray([], comment.replies), [reply]) });
194
+ return __assign(__assign({}, comment), { status: newStatus, replies: isDeleteReply
195
+ ? filterReplies(reply.replyId, comment.replies)
196
+ : __spreadArray(__spreadArray([], comment.replies), [reply]) });
197
+ }
198
+ return comment;
199
+ });
200
+ });
201
+ }, []);
202
+ var deleteReply = react_1.useCallback(function (_a) {
203
+ var uri = _a.uri, commentId = _a.commentId, reply = _a.reply;
204
+ setSending(true);
205
+ mdm_sdk_1.deleteReply({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId, replyId: reply.replyId })
206
+ .then(function () { return updateReplyInState(reply, uri, commentId, true); })
207
+ .catch(catchErrorInRequest)
208
+ .finally(function () { return setSending(false); });
209
+ }, [collaborationPath, updateReplyInState, tenant]);
210
+ var editReplyInState = react_1.useCallback(function (reply, commentId) {
211
+ setCurrentComment(function (prevCurrentComment) {
212
+ if (prevCurrentComment) {
213
+ return __assign(__assign({}, prevCurrentComment), { replies: getUpdatedReplies(prevCurrentComment, reply) });
214
+ }
215
+ });
216
+ setComments(function (prevComments) {
217
+ return prevComments.map(function (comment) {
218
+ if (comment.commentId === commentId) {
219
+ return __assign(__assign({}, comment), { replies: getUpdatedReplies(comment, reply) });
182
220
  }
183
221
  return comment;
184
222
  });
185
223
  });
186
224
  }, []);
225
+ var editReply = react_1.useCallback(function (_a) {
226
+ var content = _a.content, namedUsers = _a.namedUsers, commentId = _a.commentId, replyId = _a.replyId;
227
+ setSending(true);
228
+ var data = {
229
+ content: content,
230
+ namedUsers: namedUsers
231
+ };
232
+ return mdm_sdk_1.updateReply({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId, replyId: replyId, data: data })
233
+ .then(function (reply) { return editReplyInState(reply, commentId); })
234
+ .catch(catchErrorInRequest)
235
+ .finally(function () { return setSending(false); });
236
+ }, [collaborationPath, tenant, editReplyInState]);
187
237
  var createReply = react_1.useCallback(function (_a) {
188
238
  var content = _a.content, namedUsers = _a.namedUsers, commentId = _a.commentId, action = _a.action, uri = _a.uri;
189
239
  setSending(true);
@@ -228,7 +278,9 @@ var useCollaboration = function (_a) {
228
278
  pageToken: pageToken,
229
279
  reOpenThread: reOpenThread,
230
280
  resolveThread: resolveThread,
231
- sending: sending
281
+ sending: sending,
282
+ deleteReply: deleteReply,
283
+ editReply: editReply
232
284
  };
233
285
  };
234
286
  exports.useCollaboration = useCollaboration;
@@ -1,4 +1,4 @@
1
- import React, { useRef, useState, memo } from 'react';
1
+ import React, { useRef, memo } from 'react';
2
2
  import Box from '@material-ui/core/Box';
3
3
  import { Comment } from './Comment/Comment';
4
4
  import { RepliedComment } from './RepliedComment/RepliedComment';
@@ -8,22 +8,15 @@ export var CollaborationItem = memo(function (_a) {
8
8
  var uri = _a.uri, relatedObjectUris = _a.relatedObjectUris, objectType = _a.objectType, classes = _a.classes, popperRef = _a.popperRef, messagesRef = _a.messagesRef, comment = _a.comment;
9
9
  var inputRef = useRef();
10
10
  var styles = useStyles({ classes: classes });
11
- var _b = useState(false), isEditingComment = _b[0], setIsEditingComment = _b[1];
12
11
  var handleReply = function () {
13
- if (isEditingComment) {
14
- setIsEditingComment(false);
15
- }
16
12
  inputRef.current.focus();
17
13
  };
18
- var handleSetEdit = function () {
19
- setIsEditingComment(true);
20
- };
21
- var sendMessageArea = (React.createElement(SendMessageArea, { className: styles.sendMessageArea, inputRef: inputRef, popperRef: popperRef, uri: uri, relatedObjectUris: relatedObjectUris, objectType: objectType, comment: comment, onCancel: function () { return setIsEditingComment(false); }, isEditingComment: isEditingComment }));
14
+ var sendMessageArea = (React.createElement(SendMessageArea, { className: styles.sendMessageArea, inputRef: inputRef, popperRef: popperRef, uri: uri, relatedObjectUris: relatedObjectUris, objectType: objectType, comment: comment }));
22
15
  return (React.createElement(Box, { className: styles.root },
23
16
  comment && (React.createElement(React.Fragment, null,
24
17
  React.createElement("div", { className: styles.messages, ref: messagesRef },
25
- React.createElement(Comment, { comment: comment, uri: uri, onReply: handleReply, onStartEditing: handleSetEdit, className: styles.comment }),
26
- React.createElement(Box, { className: styles.replies }, comment.replies.map(function (reply) { return (React.createElement(RepliedComment, { key: reply.replyId, className: styles.repliedComment, reply: reply })); }))),
18
+ React.createElement(Comment, { comment: comment, uri: uri, onReply: handleReply, className: styles.comment, relatedObjectUris: relatedObjectUris, objectType: objectType }),
19
+ React.createElement(Box, { className: styles.replies }, comment.replies.map(function (reply) { return (React.createElement(RepliedComment, { key: reply.replyId, className: styles.repliedComment, reply: reply, uri: uri, comment: comment })); }))),
27
20
  sendMessageArea)),
28
21
  !comment && sendMessageArea));
29
22
  });
@@ -5,7 +5,8 @@ declare type Props = {
5
5
  onReply: () => void;
6
6
  className?: string;
7
7
  comment: CommentType;
8
- onStartEditing: () => void;
8
+ relatedObjectUris: CommentType['relatedObjectUris'];
9
+ objectType: CommentType['objectType'];
9
10
  };
10
- export declare const Comment: ({ onReply, className, uri, comment, onStartEditing }: Props) => JSX.Element;
11
+ export declare const Comment: ({ onReply, className, uri, comment, relatedObjectUris, objectType }: Props) => JSX.Element;
11
12
  export {};
@@ -1,9 +1,11 @@
1
- import React, { useMemo, useContext } from 'react';
1
+ import React, { useMemo, useContext, useState, useRef, useEffect } from 'react';
2
+ import { useSelector } from 'react-redux';
2
3
  import i18n from 'ui-i18n';
3
4
  import Link from '@material-ui/core/Link';
4
5
  import Box from '@material-ui/core/Box';
5
6
  import Typography from '@material-ui/core/Typography';
6
7
  import MoreVertIcon from '@material-ui/icons/MoreVert';
8
+ import mdm from '@reltio/mdm-module';
7
9
  import DropDownMenuButton from '../../DropDownMenuButton/DropDownMenuButton';
8
10
  import { SmallIconButtonWithTooltip } from '../../SmallIconButton';
9
11
  import { CommentTarget } from '../CommentTarget/CommentTarget';
@@ -11,44 +13,52 @@ import { CommentContent } from '../CommentContent/CommentContent';
11
13
  import { Avatar } from '../Avatar/Avatar';
12
14
  import { CollaborationContext } from '../../../contexts';
13
15
  import { formatDate } from '../utils';
16
+ import { SendMessageArea } from '../SendMessageArea/SendMessageArea';
14
17
  import { useStyles } from './styles';
15
- import { useSelector } from 'react-redux';
16
- import mdm from '@reltio/mdm-module';
17
18
  export var Comment = function (_a) {
18
- var onReply = _a.onReply, className = _a.className, uri = _a.uri, comment = _a.comment, onStartEditing = _a.onStartEditing;
19
+ var onReply = _a.onReply, className = _a.className, uri = _a.uri, comment = _a.comment, relatedObjectUris = _a.relatedObjectUris, objectType = _a.objectType;
19
20
  var styles = useStyles();
21
+ var inputRef = useRef();
22
+ var _b = useState(false), isEditingComment = _b[0], setIsEditingComment = _b[1];
20
23
  var username = useSelector(mdm.selectors.getUserName);
21
- var canChangeComment = comment.createdBy === username;
22
- var _b = useContext(CollaborationContext), resolveThread = _b.resolveThread, reOpenThread = _b.reOpenThread, sending = _b.sending, deleteComment = _b.deleteComment;
24
+ var commentId = comment.commentId, createdBy = comment.createdBy, createdTime = comment.createdTime;
25
+ var canChangeComment = createdBy === username;
26
+ var _c = useContext(CollaborationContext), resolveThread = _c.resolveThread, reOpenThread = _c.reOpenThread, sending = _c.sending, deleteComment = _c.deleteComment;
27
+ useEffect(function () {
28
+ if (isEditingComment) {
29
+ inputRef.current.focus();
30
+ }
31
+ }, [isEditingComment]);
23
32
  var menuItems = useMemo(function () { return [
24
33
  {
25
34
  text: i18n.text('Edit'),
26
- onClick: onStartEditing
35
+ onClick: function () { return setIsEditingComment(true); }
27
36
  },
28
37
  {
29
38
  text: i18n.text('Delete'),
30
- onClick: function () { return deleteComment({ uri: uri, commentId: comment.commentId }); }
39
+ onClick: function () { return deleteComment({ uri: uri, commentId: commentId }); }
31
40
  }
32
- ]; }, [onStartEditing, deleteComment, uri, comment]);
41
+ ]; }, [deleteComment, uri, commentId]);
33
42
  var handleResolve = function () {
34
- resolveThread({ commentId: comment.commentId, uri: uri });
43
+ resolveThread({ commentId: commentId, uri: uri });
35
44
  };
36
45
  var handleReOpen = function () {
37
- reOpenThread({ commentId: comment.commentId, uri: uri });
46
+ reOpenThread({ commentId: commentId, uri: uri });
38
47
  };
48
+ var sendMessageArea = (React.createElement(SendMessageArea, { inputRef: inputRef, uri: uri, relatedObjectUris: relatedObjectUris, objectType: objectType, onCancel: function () { return setIsEditingComment(false); }, isEditingComment: isEditingComment, comment: comment }));
39
49
  return (React.createElement(Box, { className: className },
40
50
  React.createElement(Box, { className: styles.header },
41
- React.createElement(Avatar, { classes: { root: styles.avatar } }, comment.createdBy),
51
+ React.createElement(Avatar, { classes: { root: styles.avatar } }, createdBy),
42
52
  React.createElement(Box, { width: "100%" },
43
- React.createElement(Typography, { className: styles.username }, comment.createdBy)),
44
- React.createElement(Typography, { className: styles.createdAt }, formatDate(comment.createdTime)),
53
+ React.createElement(Typography, { className: styles.username }, createdBy)),
54
+ React.createElement(Typography, { className: styles.createdAt }, formatDate(createdTime)),
45
55
  canChangeComment && (React.createElement(DropDownMenuButton, { buttonComponent: SmallIconButtonWithTooltip, buttonProps: {
46
56
  icon: MoreVertIcon,
47
57
  tooltipTitle: i18n.text('Open menu')
48
58
  }, popoverProps: { PopoverClasses: { root: styles.dropdownMenu } }, menuItems: menuItems, menuId: "collaboration-comment-menu" }))),
49
59
  React.createElement(Box, { className: styles.body },
50
60
  React.createElement(CommentTarget, { comment: comment, className: styles.commentTarget }),
51
- React.createElement(CommentContent, { comment: comment, className: styles.message }),
61
+ isEditingComment ? sendMessageArea : React.createElement(CommentContent, { comment: comment, className: styles.message }),
52
62
  React.createElement(Box, { className: styles.buttons },
53
63
  React.createElement(Link, { className: styles.button, onClick: onReply, component: "button" }, i18n.text('Reply')),
54
64
  comment.status === 'open' && (React.createElement(Link, { disabled: sending, className: styles.button, onClick: handleResolve, component: "button" }, i18n.text('Resolve'))),
@@ -1 +1 @@
1
- export declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"body" | "message" | "button" | "header" | "avatar" | "username" | "createdAt" | "commentTarget" | "dropdownMenu" | "buttons">;
1
+ export declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"body" | "message" | "button" | "header" | "avatar" | "username" | "buttons" | "createdAt" | "commentTarget" | "dropdownMenu">;
@@ -1,8 +1,11 @@
1
- /// <reference types="react" />
2
- import { Reply } from '@reltio/mdm-sdk';
1
+ import React from 'react';
2
+ import { Reply, Comment as CommentType } from '@reltio/mdm-sdk';
3
3
  declare type Props = {
4
4
  className?: string;
5
- reply: Pick<Reply, 'createdTime' | 'content' | 'createdBy' | 'action' | 'namedUsers'>;
5
+ reply: Pick<Reply, 'createdTime' | 'content' | 'createdBy' | 'action' | 'namedUsers' | 'replyId'>;
6
+ comment?: CommentType;
7
+ uri: string;
8
+ popperRef?: React.RefObject<any>;
6
9
  };
7
- export declare const RepliedComment: ({ className, reply }: Props) => JSX.Element;
10
+ export declare const RepliedComment: ({ className, reply, uri, comment, popperRef }: Props) => JSX.Element;
8
11
  export {};
@@ -1,23 +1,56 @@
1
- import React from 'react';
1
+ import React, { useRef, useContext, useMemo, useState, useEffect } from 'react';
2
+ import { useSelector } from 'react-redux';
2
3
  import i18n from 'ui-i18n';
3
4
  import classnames from 'classnames';
5
+ import mdm from '@reltio/mdm-module';
4
6
  import Box from '@material-ui/core/Box';
7
+ import MoreVertIcon from '@material-ui/icons/MoreVert';
5
8
  import Typography from '@material-ui/core/Typography';
6
9
  import { Avatar } from '../Avatar/Avatar';
7
10
  import { CommentContent } from '../CommentContent/CommentContent';
8
11
  import { formatDate } from '../utils';
9
12
  import { useStyles } from './styles';
13
+ import { CollaborationContext } from '../../../contexts';
14
+ import DropDownMenuButton from '../../DropDownMenuButton/DropDownMenuButton';
15
+ import { SmallIconButtonWithTooltip } from '../../SmallIconButton';
16
+ import { SendMessageArea } from '../SendMessageArea/SendMessageArea';
10
17
  export var RepliedComment = function (_a) {
11
- var className = _a.className, reply = _a.reply;
18
+ var className = _a.className, reply = _a.reply, uri = _a.uri, comment = _a.comment, popperRef = _a.popperRef;
19
+ var inputRef = useRef();
20
+ var _b = useState(false), isEditingReply = _b[0], setIsEditingReply = _b[1];
12
21
  var createdBy = reply.createdBy, action = reply.action, createdTime = reply.createdTime;
22
+ var username = useSelector(mdm.selectors.getUserName);
23
+ var canChangeReply = createdBy === username;
24
+ var deleteReply = useContext(CollaborationContext).deleteReply;
25
+ useEffect(function () {
26
+ if (isEditingReply) {
27
+ inputRef.current.focus();
28
+ }
29
+ }, [isEditingReply]);
13
30
  var styles = useStyles();
31
+ var menuItems = useMemo(function () { return [
32
+ {
33
+ text: i18n.text('Edit'),
34
+ onClick: function () { return setIsEditingReply(true); }
35
+ },
36
+ {
37
+ text: i18n.text('Delete'),
38
+ onClick: function () { return deleteReply({ uri: uri, commentId: comment.commentId, reply: reply }); }
39
+ }
40
+ ]; }, [deleteReply, uri, comment.commentId, reply]);
41
+ var sendMessageArea = (React.createElement(SendMessageArea, { inputRef: inputRef, popperRef: popperRef, uri: uri, onCancel: function () { return setIsEditingReply(false); }, isEditingReply: isEditingReply, reply: reply, comment: comment }));
14
42
  return (React.createElement(Box, { className: classnames(styles.root, className) },
15
43
  React.createElement(Avatar, { classes: { root: styles.avatar } }, createdBy),
16
- React.createElement(Box, null,
44
+ React.createElement(Box, { flexGrow: 1 },
17
45
  React.createElement(Box, { className: styles.header },
18
46
  React.createElement(Typography, { className: styles.username }, createdBy),
19
47
  action === 'resolve' && (React.createElement(Typography, { className: styles.marked }, i18n.text('Marked as resolved'))),
20
48
  action === 'reopen' && React.createElement(Typography, { className: styles.marked }, i18n.text('Re-opened'))),
21
- action !== 'resolve' && React.createElement(CommentContent, { className: styles.message, comment: reply }),
22
- React.createElement(Typography, { className: styles.createdAt }, formatDate(createdTime)))));
49
+ action !== 'resolve' &&
50
+ (isEditingReply ? sendMessageArea : React.createElement(CommentContent, { className: styles.message, comment: reply })),
51
+ React.createElement(Typography, { className: styles.createdAt }, formatDate(createdTime))),
52
+ canChangeReply && (React.createElement(DropDownMenuButton, { buttonComponent: SmallIconButtonWithTooltip, buttonProps: {
53
+ icon: MoreVertIcon,
54
+ tooltipTitle: i18n.text('Open menu')
55
+ }, menuItems: menuItems, menuId: "collaboration-comment-menu" }))));
23
56
  };
@@ -1,15 +1,17 @@
1
1
  import React from 'react';
2
- import { Comment } from '@reltio/mdm-sdk';
2
+ import { Comment, Reply } from '@reltio/mdm-sdk';
3
3
  declare type Props = {
4
4
  inputRef: React.RefObject<HTMLInputElement>;
5
5
  className?: string;
6
6
  uri: string;
7
- objectType: Comment['objectType'];
8
- relatedObjectUris: Comment['relatedObjectUris'];
7
+ objectType?: Comment['objectType'];
8
+ relatedObjectUris?: Comment['relatedObjectUris'];
9
9
  popperRef?: React.RefObject<any>;
10
10
  comment?: Comment;
11
+ reply?: Pick<Reply, 'content' | 'replyId'>;
11
12
  isEditingComment?: boolean;
13
+ isEditingReply?: boolean;
12
14
  onCancel?: () => void;
13
15
  };
14
- export declare const SendMessageArea: ({ inputRef, className, uri, relatedObjectUris, objectType, popperRef, comment, isEditingComment, onCancel }: Props) => JSX.Element;
16
+ export declare const SendMessageArea: ({ inputRef, className, uri, relatedObjectUris, objectType, popperRef, comment, reply, isEditingComment, isEditingReply, onCancel }: Props) => JSX.Element;
15
17
  export {};
@@ -2,6 +2,7 @@ import React, { useState, useContext, useEffect } from 'react';
2
2
  import i18n from 'ui-i18n';
3
3
  import classnames from 'classnames';
4
4
  import { useSelector } from 'react-redux';
5
+ import { always, cond, T } from 'ramda';
5
6
  import mdm from '@reltio/mdm-module';
6
7
  import Box from '@material-ui/core/Box';
7
8
  import Button from '@material-ui/core/Button';
@@ -9,7 +10,6 @@ import { TextFieldWithMentions } from '../TextFieldWithMentions/TextFieldWithMen
9
10
  import { Avatar } from '../Avatar/Avatar';
10
11
  import { CollaborationContext } from '../../../contexts';
11
12
  import { useStyles } from './styles';
12
- import { always, cond, T } from 'ramda';
13
13
  import { useSafePromise } from '../../../hooks';
14
14
  var getPlaceholder = function (status) {
15
15
  switch (status) {
@@ -21,8 +21,8 @@ var getPlaceholder = function (status) {
21
21
  return '';
22
22
  }
23
23
  };
24
- var getButtonText = function (status, isEditingComment) {
25
- if (isEditingComment) {
24
+ var getButtonText = function (status, isEditingComment, isEditingReply) {
25
+ if (isEditingComment || isEditingReply) {
26
26
  return i18n.text('Edit');
27
27
  }
28
28
  if (status === 'open' || status === 'resolved') {
@@ -31,10 +31,11 @@ var getButtonText = function (status, isEditingComment) {
31
31
  return i18n.text('Comment');
32
32
  };
33
33
  export var SendMessageArea = function (_a) {
34
- var inputRef = _a.inputRef, className = _a.className, uri = _a.uri, relatedObjectUris = _a.relatedObjectUris, objectType = _a.objectType, popperRef = _a.popperRef, comment = _a.comment, isEditingComment = _a.isEditingComment, onCancel = _a.onCancel;
35
- var styles = useStyles();
34
+ var inputRef = _a.inputRef, className = _a.className, uri = _a.uri, relatedObjectUris = _a.relatedObjectUris, objectType = _a.objectType, popperRef = _a.popperRef, comment = _a.comment, reply = _a.reply, isEditingComment = _a.isEditingComment, isEditingReply = _a.isEditingReply, onCancel = _a.onCancel;
35
+ var isEditing = isEditingComment || isEditingReply;
36
+ var styles = useStyles({ isEditing: isEditing });
36
37
  var username = useSelector(mdm.selectors.getUserName);
37
- var _b = useContext(CollaborationContext), createReply = _b.createReply, createComment = _b.createComment, sending = _b.sending, editComment = _b.editComment;
38
+ var _b = useContext(CollaborationContext), createReply = _b.createReply, createComment = _b.createComment, sending = _b.sending, editComment = _b.editComment, editReply = _b.editReply;
38
39
  var _c = useState(''), value = _c[0], setValue = _c[1];
39
40
  var _d = useState(''), plainTextValue = _d[0], setPlainTextValue = _d[1];
40
41
  var _e = useState([]), mentions = _e[0], setMentions = _e[1];
@@ -87,6 +88,17 @@ export var SendMessageArea = function (_a) {
87
88
  });
88
89
  }
89
90
  ],
91
+ [
92
+ always(isEditingReply),
93
+ function () {
94
+ return editReply({
95
+ content: plainTextValue,
96
+ namedUsers: mentions,
97
+ commentId: comment.commentId,
98
+ replyId: reply.replyId
99
+ });
100
+ }
101
+ ],
90
102
  [
91
103
  T,
92
104
  function () {
@@ -108,19 +120,25 @@ export var SendMessageArea = function (_a) {
108
120
  }
109
121
  }, [popperRef, shouldShowButtons]);
110
122
  useEffect(function () {
111
- if (isEditingComment) {
112
- setValue(comment.content);
123
+ if (isEditingComment || isEditingReply) {
124
+ if (isEditingComment) {
125
+ setValue(comment.content);
126
+ }
127
+ else {
128
+ setValue(reply.content);
129
+ }
113
130
  }
114
131
  else {
115
132
  clearValue();
116
133
  }
117
- }, [isEditingComment]);
134
+ }, [isEditingComment, isEditingReply]);
135
+ var buttonSize = isEditing ? 'small' : 'medium';
118
136
  return (React.createElement(Box, { className: classnames(styles.root, className) },
119
137
  React.createElement("form", { onSubmit: handleSubmit, className: styles.form },
120
138
  React.createElement(Box, { className: styles.main },
121
- React.createElement(Avatar, { classes: { root: styles.avatar } }, username),
139
+ !isEditing && React.createElement(Avatar, { classes: { root: styles.avatar } }, username),
122
140
  React.createElement(TextFieldWithMentions, { className: styles.textField, disabled: sending, onChange: handleChange, inputRef: inputRef, value: value, onFocus: handleFocus, onBlur: handleBlur, placeholder: getPlaceholder(status) })),
123
141
  shouldShowButtons && (React.createElement(Box, { className: styles.buttons },
124
- React.createElement(Button, { className: styles.button, variant: "contained", color: "primary", disabled: !hasValue || sending, type: "submit" }, getButtonText(status, isEditingComment)),
125
- React.createElement(Button, { disabled: sending, onClick: handleCancel, className: styles.button, variant: "outlined", color: "primary" }, i18n.text('Cancel')))))));
142
+ React.createElement(Button, { className: styles.button, variant: "contained", color: "primary", disabled: !hasValue || sending, type: "submit", size: buttonSize }, getButtonText(status, isEditingComment, isEditingReply)),
143
+ React.createElement(Button, { disabled: sending, onClick: handleCancel, className: styles.button, variant: "outlined", color: "primary", size: buttonSize }, i18n.text('Cancel')))))));
126
144
  };
@@ -1 +1,5 @@
1
- export declare const useStyles: (props?: any) => import("@material-ui/core/styles/withStyles").ClassNameMap<"button" | "form" | "main" | "root" | "avatar" | "buttons" | "textField">;
1
+ declare type StylesProps = {
2
+ isEditing?: boolean;
3
+ };
4
+ export declare const useStyles: (props: StylesProps) => import("@material-ui/core/styles/withStyles").ClassNameMap<"button" | "form" | "main" | "root" | "avatar" | "textField" | "buttons">;
5
+ export {};
@@ -1,12 +1,18 @@
1
1
  import { makeStyles } from '@material-ui/core/styles';
2
2
  export var useStyles = makeStyles({
3
- root: {
4
- padding: '6px 6px 6px 8px',
5
- borderRadius: '4px',
6
- backgroundColor: 'rgba(0,114,206,0.06)'
3
+ root: function (_a) {
4
+ var isEditing = _a.isEditing;
5
+ return ({
6
+ padding: isEditing ? '6px 6px 6px 0' : ' 6px 6px 6px 8px',
7
+ borderRadius: '4px',
8
+ backgroundColor: isEditing ? 'transparent' : 'rgba(0,114,206,0.06)'
9
+ });
7
10
  },
8
- textField: {
9
- maxWidth: 'calc(100% - 40px)'
11
+ textField: function (_a) {
12
+ var isEditing = _a.isEditing;
13
+ return ({
14
+ maxWidth: isEditing ? '100%' : 'calc(100% - 40px)'
15
+ });
10
16
  },
11
17
  form: {
12
18
  marginBottom: 0
@@ -18,9 +24,9 @@ export var useStyles = makeStyles({
18
24
  avatar: {
19
25
  marginRight: '8px'
20
26
  },
21
- buttons: {
22
- marginLeft: '40px',
23
- marginTop: '8px'
27
+ buttons: function (_a) {
28
+ var isEditing = _a.isEditing;
29
+ return ({ marginLeft: isEditing ? '0' : '40px', marginTop: '8px' });
24
30
  },
25
31
  button: {
26
32
  '& + $button': {
@@ -9,15 +9,13 @@ export var useStyles = makeStyles(function (theme) { return ({
9
9
  },
10
10
  '&__highlighter': {
11
11
  padding: '10px 22px',
12
- border: '1px solid transparent !important',
13
- maxHeight: '70px'
12
+ border: '1px solid transparent !important'
14
13
  },
15
14
  '&__input': {
16
15
  borderRadius: '2px',
17
16
  border: '1px solid rgba(0,0,0,0.12)',
18
17
  padding: '10px 22px',
19
18
  outline: 0,
20
- maxHeight: '70px',
21
19
  overflow: 'auto !important'
22
20
  },
23
21
  '&__suggestions': {
@@ -14,9 +14,17 @@ export declare const CollaborationContext: React.Context<{
14
14
  editComment: (params: Pick<Comment, 'content' | 'namedUsers' | 'objectType' | 'relatedObjectUris' | 'commentId' | 'replies'> & {
15
15
  uri: string;
16
16
  }) => Promise<void>;
17
+ editReply: (params: Pick<Reply, 'content' | 'namedUsers' | 'replyId'> & {
18
+ commentId: string;
19
+ }) => Promise<void>;
17
20
  deleteComment: (params: Pick<Comment, 'commentId'> & {
18
21
  uri: string;
19
22
  }) => void;
23
+ deleteReply: (params: {
24
+ uri: string;
25
+ commentId: string;
26
+ reply: Pick<Reply, 'action' | 'replyId'>;
27
+ }) => void;
20
28
  createReply: (params: Pick<Reply, 'content' | 'namedUsers' | 'action'> & {
21
29
  uri: string;
22
30
  commentId: string;
@@ -16,6 +16,8 @@ export var CollaborationContext = React.createContext({
16
16
  deleteComment: noop,
17
17
  sending: false,
18
18
  loading: false,
19
- pageToken: null
19
+ pageToken: null,
20
+ deleteReply: noop,
21
+ editReply: function () { return new Promise(noop); }
20
22
  });
21
23
  CollaborationContext.displayName = 'CollaborationContext';
@@ -22,5 +22,7 @@ export declare const useCollaboration: ({ objectIds, objectTypes, enabled }: Pro
22
22
  reOpenThread: ({ commentId, uri }: any) => void;
23
23
  resolveThread: ({ commentId, uri }: any) => void;
24
24
  sending: boolean;
25
+ deleteReply: ({ uri, commentId, reply }: any) => void;
26
+ editReply: ({ content, namedUsers, commentId, replyId }: any) => Promise<void>;
25
27
  };
26
28
  export {};
@@ -17,8 +17,18 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from) {
17
17
  import { useCallback, useEffect, useState } from 'react';
18
18
  import { useSelector } from 'react-redux';
19
19
  import { andThen, fromPairs, map, otherwise, pipe, props, uniqBy, prop, propEq, when, always } from 'ramda';
20
- import { createComment as createCommentRequest, createReply as createReplyRequest, getComment as getCommentRequest, getCommentsCount as getCommentsCountRequest, updateComment as updateCommentRequest, deleteComment as deleteCommentRequest, getComments as getCommentsRequest, isTempUri } from '@reltio/mdm-sdk';
20
+ import { createComment as createCommentRequest, createReply as createReplyRequest, getComment as getCommentRequest, getCommentsCount as getCommentsCountRequest, updateComment as updateCommentRequest, updateReply as updateReplyRequest, deleteComment as deleteCommentRequest, deleteReply as deleteReplyRequest, getComments as getCommentsRequest, isTempUri } from '@reltio/mdm-sdk';
21
21
  import mdm from '@reltio/mdm-module';
22
+ var filterReplies = function (replyId, replies) { return replies.filter(function (reply) { return reply.replyId !== replyId; }); };
23
+ var getUpdatedReplies = function (comment, reply) {
24
+ var changedReplyIndex = comment.replies.findIndex(function (_a) {
25
+ var replyId = _a.replyId;
26
+ return replyId === reply.replyId;
27
+ });
28
+ var newReplies = __spreadArray([], comment.replies);
29
+ newReplies[changedReplyIndex] = reply;
30
+ return newReplies;
31
+ };
22
32
  var defaultObjectIds = [];
23
33
  var catchErrorInRequest = function (e) { return console.error('Collaboration error', e); };
24
34
  export var useCollaboration = function (_a) {
@@ -144,8 +154,9 @@ export var useCollaboration = function (_a) {
144
154
  .catch(catchErrorInRequest)
145
155
  .finally(function () { return setSending(false); });
146
156
  }, [collaborationPath, tenant]);
147
- var updateReplyInState = useCallback(function (reply, uri, commentId) {
157
+ var updateReplyInState = useCallback(function (reply, uri, commentId, isDeleteReply) {
148
158
  var newStatus = reply.action === 'resolve' ? 'resolved' : 'open';
159
+ var replyId = reply.replyId;
149
160
  if (newStatus === 'resolved') {
150
161
  setCurrentComment(function (prevCurrentComment) {
151
162
  if (prevCurrentComment) {
@@ -156,7 +167,9 @@ export var useCollaboration = function (_a) {
156
167
  else {
157
168
  setCurrentComment(function (prevCurrentComment) {
158
169
  if (prevCurrentComment) {
159
- return __assign(__assign({}, prevCurrentComment), { replies: __spreadArray(__spreadArray([], prevCurrentComment.replies), [reply]) });
170
+ return __assign(__assign({}, prevCurrentComment), { replies: isDeleteReply
171
+ ? filterReplies(replyId, prevCurrentComment.replies)
172
+ : __spreadArray(__spreadArray([], prevCurrentComment.replies), [reply]) });
160
173
  }
161
174
  });
162
175
  }
@@ -164,7 +177,7 @@ export var useCollaboration = function (_a) {
164
177
  var _a;
165
178
  return (__assign(__assign({}, prevCommentsMap), (_a = {}, _a[uri] = (prevCommentsMap[uri] || []).map(function (comment) {
166
179
  if (comment.commentId === commentId) {
167
- return __assign(__assign({}, comment), { status: newStatus, replies: comment.replies + 1 });
180
+ return __assign(__assign({}, comment), { status: newStatus, replies: isDeleteReply ? comment.replies - 1 : comment.replies + 1 });
168
181
  }
169
182
  return comment;
170
183
  }), _a)));
@@ -172,12 +185,49 @@ export var useCollaboration = function (_a) {
172
185
  setComments(function (prevComments) {
173
186
  return prevComments.map(function (comment) {
174
187
  if (comment.commentId === commentId) {
175
- return __assign(__assign({}, comment), { status: newStatus, replies: __spreadArray(__spreadArray([], comment.replies), [reply]) });
188
+ return __assign(__assign({}, comment), { status: newStatus, replies: isDeleteReply
189
+ ? filterReplies(reply.replyId, comment.replies)
190
+ : __spreadArray(__spreadArray([], comment.replies), [reply]) });
191
+ }
192
+ return comment;
193
+ });
194
+ });
195
+ }, []);
196
+ var deleteReply = useCallback(function (_a) {
197
+ var uri = _a.uri, commentId = _a.commentId, reply = _a.reply;
198
+ setSending(true);
199
+ deleteReplyRequest({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId, replyId: reply.replyId })
200
+ .then(function () { return updateReplyInState(reply, uri, commentId, true); })
201
+ .catch(catchErrorInRequest)
202
+ .finally(function () { return setSending(false); });
203
+ }, [collaborationPath, updateReplyInState, tenant]);
204
+ var editReplyInState = useCallback(function (reply, commentId) {
205
+ setCurrentComment(function (prevCurrentComment) {
206
+ if (prevCurrentComment) {
207
+ return __assign(__assign({}, prevCurrentComment), { replies: getUpdatedReplies(prevCurrentComment, reply) });
208
+ }
209
+ });
210
+ setComments(function (prevComments) {
211
+ return prevComments.map(function (comment) {
212
+ if (comment.commentId === commentId) {
213
+ return __assign(__assign({}, comment), { replies: getUpdatedReplies(comment, reply) });
176
214
  }
177
215
  return comment;
178
216
  });
179
217
  });
180
218
  }, []);
219
+ var editReply = useCallback(function (_a) {
220
+ var content = _a.content, namedUsers = _a.namedUsers, commentId = _a.commentId, replyId = _a.replyId;
221
+ setSending(true);
222
+ var data = {
223
+ content: content,
224
+ namedUsers: namedUsers
225
+ };
226
+ return updateReplyRequest({ collaborationPath: collaborationPath, tenant: tenant, commentId: commentId, replyId: replyId, data: data })
227
+ .then(function (reply) { return editReplyInState(reply, commentId); })
228
+ .catch(catchErrorInRequest)
229
+ .finally(function () { return setSending(false); });
230
+ }, [collaborationPath, tenant, editReplyInState]);
181
231
  var createReply = useCallback(function (_a) {
182
232
  var content = _a.content, namedUsers = _a.namedUsers, commentId = _a.commentId, action = _a.action, uri = _a.uri;
183
233
  setSending(true);
@@ -222,6 +272,8 @@ export var useCollaboration = function (_a) {
222
272
  pageToken: pageToken,
223
273
  reOpenThread: reOpenThread,
224
274
  resolveThread: resolveThread,
225
- sending: sending
275
+ sending: sending,
276
+ deleteReply: deleteReply,
277
+ editReply: editReply
226
278
  };
227
279
  };
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@reltio/components",
3
- "version": "1.4.1164",
3
+ "version": "1.4.1165",
4
4
  "license": "SEE LICENSE IN LICENSE FILE",
5
5
  "main": "./cjs/index.js",
6
6
  "module": "./esm/index.js",
7
7
  "dependencies": {
8
8
  "@date-io/moment": "^1.3.5",
9
9
  "@react-google-maps/api": "2.7.0",
10
- "@reltio/mdm-module": "^1.4.1164",
11
- "@reltio/mdm-sdk": "^1.4.1164",
10
+ "@reltio/mdm-module": "^1.4.1165",
11
+ "@reltio/mdm-sdk": "^1.4.1165",
12
12
  "classnames": "^2.2.5",
13
13
  "d3-cloud": "^1.2.5",
14
14
  "d3-geo": "^2.0.1",