@topconsultnpm/sdkui-react-beta 6.14.82 → 6.14.83
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.
|
@@ -222,7 +222,7 @@ const TMBlogCommentForm = (props) => {
|
|
|
222
222
|
// Update the state with selected draft items
|
|
223
223
|
setCurrentDraftAttachments(selectedDraftItems);
|
|
224
224
|
};
|
|
225
|
-
return _jsx(TMSaveForm, { id: 1, title: SDKUI_Localizator.
|
|
225
|
+
return _jsx(TMSaveForm, { id: 1, title: SDKUI_Localizator.AddNewComment, showTitleFormMode: false, showErrorCount: false, showSaveButton: !showAttachmentsForm, showUndoButton: false, hasNavigation: false, skipIsModifiedCheck: true, isModal: true, width: calcResponsiveSizes(deviceType, '800px', '800px', '95%'), height: '550px', formMode: FormModes.Create, validationItems: validationItems, exception: exception, isModified: calcIsModified(formData, formDataOrig), onSaveAsync: onSaveAsync, onClose: onCloseCallback, customToolbarElements: _jsx("div", { style: { display: 'flex', gap: '2px' }, children: _jsx(TMButton, { btnStyle: "toolbar", icon: isEditorEnabled ? _jsx("i", { className: 'dx-icon-font' }) : _jsx("i", { className: 'dx-icon-background' }), caption: isEditorEnabled ? SDKUI_Localizator.HideFormattingOptions : SDKUI_Localizator.ShowFormattingOptions, onClick: toggleEditorMode }) }), children: _jsxs("div", { style: { width: "100%", height: "100%" }, children: [_jsxs("div", { style: { width: "100%", height: "100%" }, children: [_jsx("div", { style: { width: "100%", height: showAttachmentsSection ? "calc(100% - 60px)" : "100%" }, children: _jsx(TMHtmlEditor, { width: '100%', height: '100%', isEditorEnabled: isEditorEnabled, validationItems: validationItems, onValueChanged: onValueChanged, mentionsConfig: mentionsConfig, autoFocus: true }) }), showAttachmentsSection && _jsxs("div", { style: { display: 'flex', alignItems: 'center', height: '60px', marginTop: '10px' }, children: [_jsx("div", { style: {
|
|
226
226
|
width: 'calc(100% - 60px)',
|
|
227
227
|
overflowX: 'auto',
|
|
228
228
|
whiteSpace: 'nowrap',
|
|
@@ -11,7 +11,7 @@ import { TMColors } from '../../utils/theme';
|
|
|
11
11
|
import TMValidationItemsList from '../grids/TMValidationItemsList';
|
|
12
12
|
import TMModal from '../base/TMModal';
|
|
13
13
|
import { DeviceType, useDeviceType } from '../base/TMDeviceProvider';
|
|
14
|
-
const TMSaveForm = ({ id, formMode = FormModes.Update, showToolbar = true, skipIsModifiedCheck = false, title, children, isModal, exception, customToolbarElements, hasNavigation, showSaveButton = true, showBackButton, showWarningsCount = true, showErrorCount = true, showUndoButton = true, onClose, onSaveAsync, onNext, onPrev, canNext, canPrev, isModified, onShowList, validationItems = [], onUndo, onCancel, width, height, askClosingConfirm = false, showTitleFormMode = true }) => {
|
|
14
|
+
const TMSaveForm = ({ id, formMode = FormModes.Update, showToolbar = true, skipIsModifiedCheck = false, title, children, isModal, exception, customToolbarElements, hasNavigation, showSaveButton = true, customSaveButton, showBackButton, showWarningsCount = true, showErrorCount = true, showUndoButton = true, onClose, onSaveAsync, onNext, onPrev, canNext, canPrev, isModified, onShowList, validationItems = [], onUndo, onCancel, width, height, askClosingConfirm = false, showTitleFormMode = true }) => {
|
|
15
15
|
const [showList, setShowList] = useState(true);
|
|
16
16
|
const [showErrorGrid, setShowErrorGrid] = useState(false);
|
|
17
17
|
const deviceType = useDeviceType();
|
|
@@ -93,7 +93,7 @@ const TMSaveForm = ({ id, formMode = FormModes.Update, showToolbar = true, skipI
|
|
|
93
93
|
const warningsCount = validationItems.filter(o => o.ResultType == ResultTypes.WARNING).length;
|
|
94
94
|
const errorsCount = validationItems.filter(o => o.ResultType == ResultTypes.ERROR).length;
|
|
95
95
|
const renderSaveForm = () => {
|
|
96
|
-
return (_jsxs(TMLayoutContainer, { direction: 'vertical', children: [showToolbar && _jsx(TMLayoutItem, { height: 'max-content', children: _jsxs(StyledToolbarForm, { children: [showBackButton && _jsx(TMButton, { btnStyle: 'toolbar', color: 'tertiary', caption: SDKUI_Localizator.Back, icon: _jsx(IconArrowLeft, {}), elementStyle: { marginRight: '10px' }, onClick: () => { doClose(); } }), showSaveButton && _jsx(TMButton, { caption: SDKUI_Localizator.Save, icon: _jsx(IconSave, {}), keyGesture: "alt+s", backgroundColor: errorsCount > 0 ? TMColors.error : isModified ? TMColors.success : TMColors.disabled, onClick: doSaveAsync, color: "success", btnStyle: "toolbar", disabled: !(isModified && errorsCount <= 0) }), hasNavigation && _jsx(TMButton, { caption: SDKUI_Localizator.Previous, icon: _jsx(IconArrowUp, {}), btnStyle: "toolbar", disabled: !canPrev || isModified || formMode == FormModes.Create || formMode == FormModes.Duplicate, onClick: doPrev }), hasNavigation && _jsx(TMButton, { caption: SDKUI_Localizator.Next, icon: _jsx(IconArrowDown, {}), btnStyle: "toolbar", disabled: !canNext || isModified || formMode == FormModes.Create || formMode == FormModes.Duplicate, onClick: doNext }), showUndoButton && _jsx(TMButton, { caption: SDKUI_Localizator.Undo, icon: _jsx(IconUndo, {}), keyGesture: "alt+z", color: "tertiary", btnStyle: "toolbar", disabled: isModified ? false : true, onClick: onUndo }), customToolbarElements, Boolean(showWarningsCount && warningsCount > 0) &&
|
|
96
|
+
return (_jsxs(TMLayoutContainer, { direction: 'vertical', children: [showToolbar && _jsx(TMLayoutItem, { height: 'max-content', children: _jsxs(StyledToolbarForm, { children: [showBackButton && _jsx(TMButton, { btnStyle: 'toolbar', color: 'tertiary', caption: SDKUI_Localizator.Back, icon: _jsx(IconArrowLeft, {}), elementStyle: { marginRight: '10px' }, onClick: () => { doClose(); } }), showSaveButton && _jsx(TMButton, { caption: SDKUI_Localizator.Save, icon: customSaveButton ?? _jsx(IconSave, {}), keyGesture: "alt+s", backgroundColor: errorsCount > 0 ? TMColors.error : isModified ? TMColors.success : TMColors.disabled, onClick: doSaveAsync, color: "success", btnStyle: "toolbar", disabled: !(isModified && errorsCount <= 0) }), hasNavigation && _jsx(TMButton, { caption: SDKUI_Localizator.Previous, icon: _jsx(IconArrowUp, {}), btnStyle: "toolbar", disabled: !canPrev || isModified || formMode == FormModes.Create || formMode == FormModes.Duplicate, onClick: doPrev }), hasNavigation && _jsx(TMButton, { caption: SDKUI_Localizator.Next, icon: _jsx(IconArrowDown, {}), btnStyle: "toolbar", disabled: !canNext || isModified || formMode == FormModes.Create || formMode == FormModes.Duplicate, onClick: doNext }), showUndoButton && _jsx(TMButton, { caption: SDKUI_Localizator.Undo, icon: _jsx(IconUndo, {}), keyGesture: "alt+z", color: "tertiary", btnStyle: "toolbar", disabled: isModified ? false : true, onClick: onUndo }), customToolbarElements, Boolean(showWarningsCount && warningsCount > 0) &&
|
|
97
97
|
_jsx(TMLayoutItem, { width: 'fit-content', height: '90%', children: _jsxs(StyledResultTypeContainer, { style: { marginLeft: '10px' }, onClick: () => setShowErrorGrid(!showErrorGrid), "$resultType": ResultTypes.WARNING, children: [" ", _jsx(IconWarning, { fontSize: 16 }), " ", _jsx("span", { children: warningsCount })] }) }), Boolean(showErrorCount && errorsCount > 0) &&
|
|
98
98
|
_jsx(TMLayoutItem, { width: 'fit-content', height: '90%', children: _jsxs(StyledResultTypeContainer, { style: { marginLeft: warningsCount <= 0 ? '10px' : '0' }, onClick: () => setShowErrorGrid(!showErrorGrid), "$resultType": ResultTypes.ERROR, children: [" ", _jsx(IconCloseCircle, { fontSize: 16 }), " ", _jsx("span", { children: errorsCount })] }) }), onShowList &&
|
|
99
99
|
_jsx("div", { style: { right: '10px', position: 'absolute' }, children: deviceType !== DeviceType.MOBILE && _jsx(TMButton, { caption: showList ? SDKUI_Localizator.List_Hide : SDKUI_Localizator.List_Show, icon: showList ? _jsx(IconHide, {}) : _jsx(IconShow, {}), keyGesture: "alt+h", onClick: () => { setShowList(!showList); onShowList?.(!showList); }, btnStyle: 'toolbar' }) }), (formMode == FormModes.Create || formMode == FormModes.Duplicate) &&
|
|
@@ -89,6 +89,8 @@ interface TMBlogsProps {
|
|
|
89
89
|
context?: TMBlogContextDescriptor;
|
|
90
90
|
/** Optional layout mode */
|
|
91
91
|
layoutMode?: 'stacked' | 'chat';
|
|
92
|
+
/** Optional callback to mark blog as read */
|
|
93
|
+
markBlogAsRead?: (blog: BlogPost | undefined) => Promise<void>;
|
|
92
94
|
}
|
|
93
95
|
declare const TMBlogs: (props: TMBlogsProps) => import("react/jsx-runtime").JSX.Element;
|
|
94
96
|
export default TMBlogs;
|
|
@@ -30,7 +30,7 @@ const TMBlogs = (props) => {
|
|
|
30
30
|
isRestoreEnabled: false,
|
|
31
31
|
isRefreshEnabled: false,
|
|
32
32
|
isCreateContextualTask: false,
|
|
33
|
-
}, refreshCallback, newPosts = [], showCommentFormCallback, showTaskFormCallback, showContextMenu = true, handleAttachmentFocus, showFloatingCommentButton = false, context, layoutMode = 'stacked' } = props;
|
|
33
|
+
}, refreshCallback, newPosts = [], showCommentFormCallback, showTaskFormCallback, showContextMenu = true, handleAttachmentFocus, showFloatingCommentButton = false, context, layoutMode = 'stacked', markBlogAsRead } = props;
|
|
34
34
|
// Get the current device type (e.g., mobile, tablet, desktop) using a custom hook.
|
|
35
35
|
const deviceType = useDeviceType();
|
|
36
36
|
const { abortController, showWaitPanel, waitPanelTitle, showPrimary, waitPanelTextPrimary, waitPanelValuePrimary, waitPanelMaxValuePrimary, showSecondary, waitPanelTextSecondary, waitPanelValueSecondary, waitPanelMaxValueSecondary, downloadDcmtsAsync } = useDcmtOperations();
|
|
@@ -38,6 +38,7 @@ const TMBlogs = (props) => {
|
|
|
38
38
|
let isMobile = useMemo(() => { return deviceType === DeviceType.MOBILE; }, [deviceType]);
|
|
39
39
|
// State to store an array of blog posts, which can be either BlogPost or HomeBlogPost type
|
|
40
40
|
const [blogPosts, setBlogPosts] = useState([]);
|
|
41
|
+
const [firstNewPost, setFirstNewPost] = useState(undefined);
|
|
41
42
|
// State to manage the data source for a tree component
|
|
42
43
|
const [treeDataSource, setTreeDataSource] = useState([]);
|
|
43
44
|
// State to store the user's search input for filtering or searching posts/messages
|
|
@@ -61,11 +62,6 @@ const TMBlogs = (props) => {
|
|
|
61
62
|
const [isHeaderHidden, setIsHeaderHidden] = useState(isHeaderFullyHidden(currentHeader));
|
|
62
63
|
// showId is a state variable that determines whether an ID-related component or feature should be displayed
|
|
63
64
|
const [localShowId, setLocalShowId] = useState(false);
|
|
64
|
-
// State variable to track the new posts
|
|
65
|
-
const [newPostIds, setNewPostIds] = useState(new Set());
|
|
66
|
-
const firstNewPostIndex = useMemo(() => {
|
|
67
|
-
return blogPosts.findIndex(post => post.id !== undefined && newPostIds.has(post.id));
|
|
68
|
-
}, [blogPosts, newPostIds]);
|
|
69
65
|
// Ref to the container
|
|
70
66
|
const containerRef = useRef(null);
|
|
71
67
|
// State variable to control the visibility of the wait panel.
|
|
@@ -180,6 +176,8 @@ const TMBlogs = (props) => {
|
|
|
180
176
|
setFocusedAttachment(undefined);
|
|
181
177
|
if (handleAttachmentFocus)
|
|
182
178
|
handleAttachmentFocus(undefined);
|
|
179
|
+
if (markBlogAsRead)
|
|
180
|
+
markBlogAsRead(blog);
|
|
183
181
|
};
|
|
184
182
|
const refresh = () => {
|
|
185
183
|
if (refreshCallback)
|
|
@@ -290,24 +288,6 @@ const TMBlogs = (props) => {
|
|
|
290
288
|
];
|
|
291
289
|
return menuItemsElements;
|
|
292
290
|
}, [isHeaderHidden, localShowId, setLocalShowId, focusedBlog, focusedAttachment, showDcmtForm]);
|
|
293
|
-
useEffect(() => {
|
|
294
|
-
// Check if context exists, the engine is 'WorkingGroupEngine',
|
|
295
|
-
if (context && context.engine === 'WorkingGroupEngine' && context.object && context.object.id) {
|
|
296
|
-
// Find the number of new posts for the active working group
|
|
297
|
-
const newPostsCount = newPosts?.find(d => d.id === context.object?.id)?.count ?? 0;
|
|
298
|
-
// If there are no blog posts or the count of new posts is 0 or less, reset the set of new post IDs to an empty set and exit early
|
|
299
|
-
if (blogPosts.length === 0 || newPostsCount <= 0) {
|
|
300
|
-
setNewPostIds(new Set());
|
|
301
|
-
return;
|
|
302
|
-
}
|
|
303
|
-
// Calculate the starting index for slicing the blogPosts array to get only
|
|
304
|
-
const startIndex = Math.max(blogPosts.length - newPostsCount, 0);
|
|
305
|
-
// Extract the IDs of the posts from that slice and filter out undefined IDs
|
|
306
|
-
const ids = blogPosts.slice(startIndex).map(post => post.id).filter((id) => id !== undefined);
|
|
307
|
-
// Update the state with the new set of post IDs considered 'new'
|
|
308
|
-
setNewPostIds(new Set(ids));
|
|
309
|
-
}
|
|
310
|
-
}, [blogPosts, newPosts, context]);
|
|
311
291
|
useEffect(() => {
|
|
312
292
|
if (showId !== undefined)
|
|
313
293
|
setLocalShowId(showId);
|
|
@@ -326,7 +306,6 @@ const TMBlogs = (props) => {
|
|
|
326
306
|
if (blogPost.attachments) {
|
|
327
307
|
for (const attachment of blogPost.attachments) {
|
|
328
308
|
const dcmtTypeDescriptor = await DcmtTypeListCacheService.GetAsync(attachment.tid, true);
|
|
329
|
-
// console.log('TMBlogs - getDcmtTypeDescriptor', dcmtTypeDescriptor);
|
|
330
309
|
if (dcmtTypeDescriptor && attachment.tid) {
|
|
331
310
|
dcmtTypeMap.set(attachment.tid, dcmtTypeDescriptor);
|
|
332
311
|
}
|
|
@@ -408,6 +387,7 @@ const TMBlogs = (props) => {
|
|
|
408
387
|
}
|
|
409
388
|
// Update the state with the filtered and limited list of blogs
|
|
410
389
|
setBlogPosts(filteredBlogs);
|
|
390
|
+
setFirstNewPost(filteredBlogs.find(blog => blog.customData1 === 1));
|
|
411
391
|
if (focusedBlog && focusedBlog.id && filteredBlogs.find(filteredBlog => focusedBlog.id === filteredBlog.id) === undefined)
|
|
412
392
|
handleFocusedBlog(undefined);
|
|
413
393
|
}, [allData, appliedGlobalFilters, searchText, postsToShow, currentHeader]);
|
|
@@ -442,7 +422,7 @@ const TMBlogs = (props) => {
|
|
|
442
422
|
};
|
|
443
423
|
const renderBlogPostContent = (blogPost, index, isOwnComment) => {
|
|
444
424
|
const isSelected = focusedBlog?.id === blogPost.id;
|
|
445
|
-
const isNew = Boolean((blogPost.newPosts ?? 0) ||
|
|
425
|
+
const isNew = Boolean((blogPost.newPosts ?? 0) || blogPost.customData1);
|
|
446
426
|
const backgroundColors = {
|
|
447
427
|
default: layoutMode === 'stacked' ? colors.LIGHT_GRAY : isOwnComment ? '#D9EFE0' : '#F3E6E6',
|
|
448
428
|
selectedItems: isSelected ? color ?? colors.PRIMARY_BLUE : colors.PRIMARY_BLUE,
|
|
@@ -507,13 +487,13 @@ const TMBlogs = (props) => {
|
|
|
507
487
|
handleFocusedBlog(blogPost);
|
|
508
488
|
handleFocusedAttachment(undefined);
|
|
509
489
|
};
|
|
510
|
-
return (_jsxs(BlogPostContainer, { id: id + "-" + blogPost.id.toString(), ref: containerRef, "$color": textColor, "$textDecoration": blogPost.isDel ? 'line-through' : 'none', "$backgroundColor": bgColor, "$isNew":
|
|
490
|
+
return (_jsxs(BlogPostContainer, { id: id + "-" + blogPost.id.toString(), ref: containerRef, "$color": textColor, "$textDecoration": blogPost.isDel ? 'line-through' : 'none', "$backgroundColor": bgColor, "$isNew": isNew, "$canNavigate": canNavigate(), "$paddingRight": layoutMode === 'chat' ? "50px" : "10px", onClick: onClickCallback, onDoubleClick: headerClickCallback, tabIndex: 0, onKeyDown: handleKeyDown, onKeyUp: handleKeyUp, onContextMenu: onContextMenu, children: [_jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [(layoutMode !== 'chat' || !isOwnComment) && OwnerInitialsBadge(blogPost), _jsx("div", { style: { flex: "1 1 auto", minWidth: "0" }, children: _jsxs("div", { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: "wrap", overflow: "hidden" }, children: [_jsxs("div", { children: [_jsxs("div", { style: { fontWeight: "bold", fontSize: '1rem', display: "flex", alignItems: "center" }, children: [showIconHeader && blogPost.header && blogPost.classID
|
|
511
491
|
? IconAndHeaderElement(blogPost, iconColor, isSelected, () => {
|
|
512
492
|
if (handleNavigateToWGs && blogPost.id && blogPost.classID === 'WG') {
|
|
513
493
|
handleNavigateToWGs(blogPost.id);
|
|
514
494
|
}
|
|
515
495
|
}, searchText)
|
|
516
|
-
: _jsx("span", { style: { marginLeft: showIconHeader ? "5px" : "0", color: isSelected ? "#fff" : !blogPost.isSys ? TMColors.primary : colors.RED }, children: highlightText(blogPost.ownerName ?? '', searchText, isSelected) }), (blogPost?.newPosts ?? 0) > 0 && (_jsx("div", { style: {
|
|
496
|
+
: !isOwnComment && _jsx("span", { style: { marginLeft: showIconHeader ? "5px" : "0", color: isSelected ? "#fff" : !blogPost.isSys ? TMColors.primary : colors.RED }, children: highlightText(blogPost.ownerName ?? '', searchText, isSelected) }), (blogPost?.newPosts ?? 0) > 0 && (_jsx("div", { style: {
|
|
517
497
|
marginLeft: "5px",
|
|
518
498
|
minWidth: "20px",
|
|
519
499
|
height: "20px",
|
|
@@ -540,8 +520,8 @@ const TMBlogs = (props) => {
|
|
|
540
520
|
_jsx("div", { style: { fontSize: "15px", marginTop: "10px" }, children: SDKUI_Localizator.NoMessages })] })
|
|
541
521
|
: blogPosts.map((blogPost, index) => {
|
|
542
522
|
const isOwnComment = blogPost.ownerID === SDK_Globals.tmSession?.SessionDescr?.userID;
|
|
543
|
-
return (_jsxs(React.Fragment, { children: [
|
|
544
|
-
_jsx("div", {
|
|
523
|
+
return (_jsxs(React.Fragment, { children: [(firstNewPost && blogPost.id === firstNewPost.id) && (_jsxs("div", { style: { display: 'flex', alignItems: 'center', width: '100%', color: TMColors.primary, fontWeight: '600', fontSize: '0.9rem', userSelect: 'none', }, children: [_jsx("hr", { style: { flex: 1, border: 'none', borderTop: `1px solid ${TMColors.primary}`, marginRight: '10px' } }), _jsx("span", { children: SDKUI_Localizator.LastRead }), _jsx("hr", { style: { flex: 1, border: 'none', borderTop: `1px solid ${TMColors.primary}`, marginLeft: '10px' } })] })), layoutMode === 'stacked' ? renderBlogPostContent(blogPost, index, isOwnComment) :
|
|
524
|
+
_jsx("div", { style: {
|
|
545
525
|
display: "flex",
|
|
546
526
|
flexDirection: "row",
|
|
547
527
|
alignItems: "flex-start",
|
|
@@ -556,7 +536,7 @@ const TMBlogs = (props) => {
|
|
|
556
536
|
textAlign: "left",
|
|
557
537
|
maxWidth: '90%',
|
|
558
538
|
borderRadius: '8px',
|
|
559
|
-
}, children: renderBlogPostContent(blogPost, index, isOwnComment) }) }
|
|
539
|
+
}, children: renderBlogPostContent(blogPost, index, isOwnComment) }) })] }, "blog-post-wrapper-" + id + "-" + blogPost.id));
|
|
560
540
|
}) }) });
|
|
561
541
|
};
|
|
562
542
|
// Function to handle changes in the search text
|
package/lib/ts/types.d.ts
CHANGED