synapse-react-client 4.0.10 → 4.0.11

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 (89) hide show
  1. package/dist/SWC.index.js +1 -1
  2. package/dist/assets/icons/CloudWarning.d.ts +5 -0
  3. package/dist/assets/icons/CloudWarning.d.ts.map +1 -0
  4. package/dist/assets/icons/CloudWarning.js +47 -0
  5. package/dist/assets/icons/CloudWarning.js.map +1 -0
  6. package/dist/components/ChallengeSubmission/SubmissionDirectoryList.d.ts.map +1 -1
  7. package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js +143 -140
  8. package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js.map +1 -1
  9. package/dist/components/DataGrid/columns/AutocompleteColumn.d.ts.map +1 -1
  10. package/dist/components/DataGrid/columns/AutocompleteColumn.js +66 -55
  11. package/dist/components/DataGrid/columns/AutocompleteColumn.js.map +1 -1
  12. package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.d.ts.map +1 -1
  13. package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js +1 -1
  14. package/dist/components/DataGrid/columns/AutocompleteMultipleEnumColumn.js.map +1 -1
  15. package/dist/components/DataGrid/utils/applyModelChange.d.ts +1 -1
  16. package/dist/components/DataGrid/utils/applyModelChange.d.ts.map +1 -1
  17. package/dist/components/DataGrid/utils/applyModelChange.js +27 -24
  18. package/dist/components/DataGrid/utils/applyModelChange.js.map +1 -1
  19. package/dist/components/DataGrid/utils/columnFactory.d.ts +8 -0
  20. package/dist/components/DataGrid/utils/columnFactory.d.ts.map +1 -1
  21. package/dist/components/DataGrid/utils/columnFactory.js +47 -44
  22. package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
  23. package/dist/components/DataGrid/utils/getEmptyValue.d.ts +2 -0
  24. package/dist/components/DataGrid/utils/getEmptyValue.d.ts.map +1 -0
  25. package/dist/components/DataGrid/utils/getEmptyValue.js +8 -0
  26. package/dist/components/DataGrid/utils/getEmptyValue.js.map +1 -0
  27. package/dist/components/DataGrid/utils/modelColsToGrid.d.ts.map +1 -1
  28. package/dist/components/DataGrid/utils/modelColsToGrid.js +2 -1
  29. package/dist/components/DataGrid/utils/modelColsToGrid.js.map +1 -1
  30. package/dist/components/DataGrid/utils/schemaAwarePasteValue.d.ts +32 -0
  31. package/dist/components/DataGrid/utils/schemaAwarePasteValue.d.ts.map +1 -0
  32. package/dist/components/DataGrid/utils/schemaAwarePasteValue.js +22 -0
  33. package/dist/components/DataGrid/utils/schemaAwarePasteValue.js.map +1 -0
  34. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.css +1 -0
  35. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.d.ts.map +1 -1
  36. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js +199 -132
  37. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
  38. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js +22 -0
  39. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.js.map +1 -0
  40. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.module.scss +170 -0
  41. package/dist/components/EntityDownloadButton/EntityDownloadButton.d.ts.map +1 -1
  42. package/dist/components/EntityDownloadButton/EntityDownloadButton.js +1 -0
  43. package/dist/components/EntityDownloadButton/EntityDownloadButton.js.map +1 -1
  44. package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.d.ts.map +1 -1
  45. package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js +15 -14
  46. package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js.map +1 -1
  47. package/dist/components/Forum/DiscussionReply.d.ts +1 -0
  48. package/dist/components/Forum/DiscussionReply.d.ts.map +1 -1
  49. package/dist/components/Forum/DiscussionReply.js +19 -19
  50. package/dist/components/Forum/DiscussionReply.js.map +1 -1
  51. package/dist/components/Forum/DiscussionThread.d.ts +1 -0
  52. package/dist/components/Forum/DiscussionThread.d.ts.map +1 -1
  53. package/dist/components/Forum/DiscussionThread.js +73 -72
  54. package/dist/components/Forum/DiscussionThread.js.map +1 -1
  55. package/dist/components/GenericCard/BioregistryRules.d.ts.map +1 -1
  56. package/dist/components/GenericCard/BioregistryRules.js +7 -3
  57. package/dist/components/GenericCard/BioregistryRules.js.map +1 -1
  58. package/dist/components/IconSvg/IconSvg.d.ts.map +1 -1
  59. package/dist/components/IconSvg/IconSvg.js +2 -1
  60. package/dist/components/IconSvg/IconSvg.js.map +1 -1
  61. package/dist/components/dataaccess/SubmissionPage/SubmissionPage.d.ts.map +1 -1
  62. package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js +157 -148
  63. package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js.map +1 -1
  64. package/dist/components/doi/CreateOrUpdateDoiModal.d.ts.map +1 -1
  65. package/dist/components/doi/CreateOrUpdateDoiModal.js +20 -19
  66. package/dist/components/doi/CreateOrUpdateDoiModal.js.map +1 -1
  67. package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.d.ts.map +1 -1
  68. package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js +1 -1
  69. package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js.map +1 -1
  70. package/dist/synapse-queries/KeyFactory.d.ts +1 -0
  71. package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
  72. package/dist/synapse-queries/KeyFactory.js +3 -0
  73. package/dist/synapse-queries/KeyFactory.js.map +1 -1
  74. package/dist/synapse-queries/forum/useThread.d.ts +1 -0
  75. package/dist/synapse-queries/forum/useThread.d.ts.map +1 -1
  76. package/dist/synapse-queries/forum/useThread.js +19 -12
  77. package/dist/synapse-queries/forum/useThread.js.map +1 -1
  78. package/dist/tsconfig.build.tsbuildinfo +1 -1
  79. package/dist/utils/APIConstants.d.ts +1 -0
  80. package/dist/utils/APIConstants.d.ts.map +1 -1
  81. package/dist/utils/APIConstants.js +2 -2
  82. package/dist/utils/APIConstants.js.map +1 -1
  83. package/dist/utils/AppUtils/session/ApplicationSessionManager.d.ts.map +1 -1
  84. package/dist/utils/AppUtils/session/ApplicationSessionManager.js +7 -4
  85. package/dist/utils/AppUtils/session/ApplicationSessionManager.js.map +1 -1
  86. package/dist/utils/functions/EntityTypeUtils.d.ts.map +1 -1
  87. package/dist/utils/functions/EntityTypeUtils.js +15 -4
  88. package/dist/utils/functions/EntityTypeUtils.js.map +1 -1
  89. package/package.json +4 -4
@@ -22,25 +22,25 @@ var C = (n) => {
22
22
  t(`${`${window.location.origin}${window.location.pathname}`}?${p}=${n}`).then(() => e("Reply link copied to clipboard", "info"));
23
23
  };
24
24
  function w(t) {
25
- let { reply: w, isReplyAuthorModerator: T = !1 } = t, [E, D] = g(!1), [O, k] = g(!1), { data: A } = r(), { data: j } = n(w.projectId), { data: M, isLoading: N } = d(w), P = h(null), { mutate: F } = u({ onSuccess: () => {
26
- k(!1), e("A reply has been deleted.", "info");
27
- } }), I = w.createdBy == A?.ownerId;
25
+ let { reply: w, isReplyAuthorModerator: T = !1, isForumModerator: E } = t, [D, O] = g(!1), [k, A] = g(!1), { data: j } = r(), { data: M } = n(w.projectId), { data: N, isLoading: P } = d(w), F = h(null), { mutate: I } = u({ onSuccess: () => {
26
+ A(!1), e("A reply has been deleted.", "info");
27
+ } }), L = w.createdBy == j?.ownerId;
28
28
  return m(() => {
29
29
  let e = new URLSearchParams(window.location.search).get(p), t;
30
- return e === w.id && P.current && (P.current.style.transition = "background-color 1s ease", P.current.style.backgroundColor = "#fbf4e0", P.current.style.borderColor = "#f4dda3", t = setTimeout(() => {
31
- P.current && (P.current.style.backgroundColor = "#f9f9f9", P.current.style.borderColor = "#ccc");
30
+ return e === w.id && F.current && (F.current.style.transition = "background-color 1s ease", F.current.style.backgroundColor = "#fbf4e0", F.current.style.borderColor = "#f4dda3", t = setTimeout(() => {
31
+ F.current && (F.current.style.backgroundColor = "#f9f9f9", F.current.style.borderColor = "#ccc");
32
32
  }, 2e3)), () => {
33
33
  t && clearTimeout(t);
34
34
  };
35
35
  }, [w.id]), /* @__PURE__ */ y("div", {
36
36
  className: "reply-container",
37
37
  id: `reply._${w.id}`,
38
- ref: P,
38
+ ref: F,
39
39
  role: "article",
40
- children: N ? /* @__PURE__ */ y(i, {
40
+ children: P ? /* @__PURE__ */ y(i, {
41
41
  numCols: 1,
42
42
  numRows: 4
43
- }) : /* @__PURE__ */ y(v, { children: M && /* @__PURE__ */ b(v, { children: [
43
+ }) : /* @__PURE__ */ y(v, { children: N && /* @__PURE__ */ b(v, { children: [
44
44
  /* @__PURE__ */ b("div", { children: [/* @__PURE__ */ y(l, {
45
45
  userId: w.createdBy,
46
46
  withAvatar: !0,
@@ -51,7 +51,7 @@ function w(t) {
51
51
  className: "message-body",
52
52
  children: [
53
53
  /* @__PURE__ */ y(a, {
54
- markdown: M,
54
+ markdown: N,
55
55
  objectType: x.REPLY
56
56
  }),
57
57
  /* @__PURE__ */ b("span", { children: [
@@ -77,15 +77,15 @@ function w(t) {
77
77
  label: "Copy link to this reply"
78
78
  })
79
79
  }),
80
- I && /* @__PURE__ */ y("button", {
81
- onClick: () => D(!0),
80
+ L && /* @__PURE__ */ y("button", {
81
+ onClick: () => O(!0),
82
82
  children: /* @__PURE__ */ y(o, {
83
83
  icon: "edit",
84
84
  label: "Edit reply"
85
85
  })
86
86
  }),
87
- j?.permissions.canModerate && /* @__PURE__ */ y("button", {
88
- onClick: () => k(!0),
87
+ (M?.permissions.canModerate || E) && /* @__PURE__ */ y("button", {
88
+ onClick: () => A(!0),
89
89
  children: /* @__PURE__ */ y(o, {
90
90
  icon: "delete",
91
91
  label: "Delete reply"
@@ -97,20 +97,20 @@ function w(t) {
97
97
  })] }),
98
98
  /* @__PURE__ */ y(f, {
99
99
  isReply: !0,
100
- initialText: M,
101
- onClose: () => D(!1),
100
+ initialText: N,
101
+ onClose: () => O(!1),
102
102
  id: w.id,
103
103
  isDialog: !0,
104
- openDialog: E
104
+ openDialog: D
105
105
  }),
106
106
  /* @__PURE__ */ y(s, {
107
- open: O,
107
+ open: k,
108
108
  title: "Confirm Deletion",
109
109
  content: "Are you sure you want to delete this reply?",
110
110
  onCancel: () => {
111
- k(!1);
111
+ A(!1);
112
112
  },
113
- onConfirm: () => F({
113
+ onConfirm: () => I({
114
114
  forumId: w.forumId,
115
115
  threadId: w.threadId,
116
116
  replyId: w.id
@@ -1 +1 @@
1
- {"version":3,"file":"DiscussionReply.js","names":[],"sources":["../../../src/components/Forum/DiscussionReply.tsx"],"sourcesContent":["import { useGetCurrentUserProfile, useGetEntityBundle } from '@/synapse-queries'\nimport { useDeleteReply, useGetReply } from '@/synapse-queries/forum/useReply'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport {\n DiscussionReplyBundle,\n ObjectType,\n} from '@sage-bionetworks/synapse-types'\nimport dayjs from 'dayjs'\nimport { useState, useRef, useEffect } from 'react'\nimport IconSvg from '../IconSvg/IconSvg'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport { SkeletonTable } from '../Skeleton/SkeletonTable'\nimport WarningDialog from '../SynapseForm/WarningDialog'\nimport { displayToast } from '../ToastMessage/ToastMessage'\nimport { UserBadge } from '../UserCard/UserBadge'\nimport { ForumThreadEditor } from './ForumThreadEditor'\nimport { Box } from '@mui/material'\nimport { copyStringToClipboard } from '@/utils/functions/StringUtils'\nimport { REPLY_ID_PARAM_KEY } from './DiscussionConstants'\n\nexport type DiscussionReplyProps = {\n reply: DiscussionReplyBundle\n isReplyAuthorModerator?: boolean\n onClickLink?: () => void\n}\n\nconst handleCopyLink = (id: string) => {\n const baseUrl = `${window.location.origin}${window.location.pathname}`\n const url = `${baseUrl}?${REPLY_ID_PARAM_KEY}=${id}`\n copyStringToClipboard(url).then(() =>\n displayToast('Reply link copied to clipboard', 'info'),\n )\n}\n\nexport function DiscussionReply(props: DiscussionReplyProps) {\n const { reply, isReplyAuthorModerator = false } = props\n const [showReplyModal, setShowReplyModal] = useState(false)\n const [showDeleteModal, setShowDeleteModal] = useState(false)\n const { data: currentUserProfile } = useGetCurrentUserProfile()\n const { data: entityBundle } = useGetEntityBundle(reply.projectId)\n const { data: message, isLoading } = useGetReply(reply)\n const replyRef = useRef<HTMLDivElement>(null)\n\n const { mutate: deleteReply } = useDeleteReply({\n onSuccess: () => {\n setShowDeleteModal(false)\n displayToast('A reply has been deleted.', 'info')\n },\n })\n\n const isCurrentUserAuthor = reply.createdBy == currentUserProfile?.ownerId\n\n useEffect(() => {\n const params = new URLSearchParams(window.location.search)\n const replyId = params.get(REPLY_ID_PARAM_KEY)\n let timerId: ReturnType<typeof setTimeout>\n if (replyId === reply.id && replyRef.current) {\n replyRef.current.style.transition = 'background-color 1s ease'\n replyRef.current.style.backgroundColor = '#fbf4e0'\n replyRef.current.style.borderColor = '#f4dda3'\n timerId = setTimeout(() => {\n if (replyRef.current) {\n replyRef.current.style.backgroundColor = '#f9f9f9'\n replyRef.current.style.borderColor = '#ccc'\n }\n }, 2000)\n }\n return () => {\n if (timerId) {\n clearTimeout(timerId)\n }\n }\n }, [reply.id])\n\n return (\n <div\n className=\"reply-container\"\n id={`reply._${reply.id}`}\n ref={replyRef}\n role={'article'}\n >\n {isLoading ? (\n <SkeletonTable numCols={1} numRows={4} />\n ) : (\n <>\n {message && (\n <>\n <div>\n <UserBadge\n userId={reply.createdBy}\n withAvatar={true}\n avatarSize=\"MEDIUM\"\n showCardOnHover={true}\n showModeratorBadge={isReplyAuthorModerator}\n />\n <div className=\"message-body\">\n <MarkdownSynapse\n markdown={message}\n objectType={ObjectType.REPLY}\n />\n <span>\n posted {formatDate(dayjs(reply.createdOn), 'M/D/YYYY')}\n {reply.isEdited ? <i>{' (Edited)'}</i> : null}\n </span>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'flex-end',\n marginTop: { xs: '8px', sm: 0 },\n float: { sm: 'right' },\n }}\n >\n <button onClick={() => handleCopyLink(reply.id)}>\n <IconSvg icon=\"link\" label={'Copy link to this reply'} />\n </button>\n {isCurrentUserAuthor && (\n <button onClick={() => setShowReplyModal(true)}>\n <IconSvg icon=\"edit\" label={'Edit reply'} />\n </button>\n )}\n {entityBundle?.permissions.canModerate && (\n <button onClick={() => setShowDeleteModal(true)}>\n <IconSvg icon=\"delete\" label={'Delete reply'} />\n </button>\n )}\n </Box>\n </div>\n </div>\n <ForumThreadEditor\n isReply={true}\n initialText={message}\n onClose={() => setShowReplyModal(false)}\n id={reply.id}\n isDialog={true}\n openDialog={showReplyModal}\n />\n <WarningDialog\n open={showDeleteModal}\n title=\"Confirm Deletion\"\n content=\"Are you sure you want to delete this reply?\"\n onCancel={() => {\n setShowDeleteModal(false)\n }}\n onConfirm={() =>\n deleteReply({\n forumId: reply.forumId,\n threadId: reply.threadId,\n replyId: reply.id,\n })\n }\n confirmButtonColor=\"error\"\n confirmButtonText=\"Delete\"\n />\n </>\n )}\n </>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DiscussionReply.js","names":[],"sources":["../../../src/components/Forum/DiscussionReply.tsx"],"sourcesContent":["import { useGetCurrentUserProfile, useGetEntityBundle } from '@/synapse-queries'\nimport { useDeleteReply, useGetReply } from '@/synapse-queries/forum/useReply'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport {\n DiscussionReplyBundle,\n ObjectType,\n} from '@sage-bionetworks/synapse-types'\nimport dayjs from 'dayjs'\nimport { useState, useRef, useEffect } from 'react'\nimport IconSvg from '../IconSvg/IconSvg'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport { SkeletonTable } from '../Skeleton/SkeletonTable'\nimport WarningDialog from '../SynapseForm/WarningDialog'\nimport { displayToast } from '../ToastMessage/ToastMessage'\nimport { UserBadge } from '../UserCard/UserBadge'\nimport { ForumThreadEditor } from './ForumThreadEditor'\nimport { Box } from '@mui/material'\nimport { copyStringToClipboard } from '@/utils/functions/StringUtils'\nimport { REPLY_ID_PARAM_KEY } from './DiscussionConstants'\n\nexport type DiscussionReplyProps = {\n reply: DiscussionReplyBundle\n isReplyAuthorModerator?: boolean\n isForumModerator?: boolean\n onClickLink?: () => void\n}\n\nconst handleCopyLink = (id: string) => {\n const baseUrl = `${window.location.origin}${window.location.pathname}`\n const url = `${baseUrl}?${REPLY_ID_PARAM_KEY}=${id}`\n copyStringToClipboard(url).then(() =>\n displayToast('Reply link copied to clipboard', 'info'),\n )\n}\n\nexport function DiscussionReply(props: DiscussionReplyProps) {\n const { reply, isReplyAuthorModerator = false, isForumModerator } = props\n const [showReplyModal, setShowReplyModal] = useState(false)\n const [showDeleteModal, setShowDeleteModal] = useState(false)\n const { data: currentUserProfile } = useGetCurrentUserProfile()\n const { data: entityBundle } = useGetEntityBundle(reply.projectId)\n const { data: message, isLoading } = useGetReply(reply)\n const replyRef = useRef<HTMLDivElement>(null)\n\n const { mutate: deleteReply } = useDeleteReply({\n onSuccess: () => {\n setShowDeleteModal(false)\n displayToast('A reply has been deleted.', 'info')\n },\n })\n\n const isCurrentUserAuthor = reply.createdBy == currentUserProfile?.ownerId\n\n useEffect(() => {\n const params = new URLSearchParams(window.location.search)\n const replyId = params.get(REPLY_ID_PARAM_KEY)\n let timerId: ReturnType<typeof setTimeout>\n if (replyId === reply.id && replyRef.current) {\n replyRef.current.style.transition = 'background-color 1s ease'\n replyRef.current.style.backgroundColor = '#fbf4e0'\n replyRef.current.style.borderColor = '#f4dda3'\n timerId = setTimeout(() => {\n if (replyRef.current) {\n replyRef.current.style.backgroundColor = '#f9f9f9'\n replyRef.current.style.borderColor = '#ccc'\n }\n }, 2000)\n }\n return () => {\n if (timerId) {\n clearTimeout(timerId)\n }\n }\n }, [reply.id])\n\n return (\n <div\n className=\"reply-container\"\n id={`reply._${reply.id}`}\n ref={replyRef}\n role={'article'}\n >\n {isLoading ? (\n <SkeletonTable numCols={1} numRows={4} />\n ) : (\n <>\n {message && (\n <>\n <div>\n <UserBadge\n userId={reply.createdBy}\n withAvatar={true}\n avatarSize=\"MEDIUM\"\n showCardOnHover={true}\n showModeratorBadge={isReplyAuthorModerator}\n />\n <div className=\"message-body\">\n <MarkdownSynapse\n markdown={message}\n objectType={ObjectType.REPLY}\n />\n <span>\n posted {formatDate(dayjs(reply.createdOn), 'M/D/YYYY')}\n {reply.isEdited ? <i>{' (Edited)'}</i> : null}\n </span>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'flex-end',\n marginTop: { xs: '8px', sm: 0 },\n float: { sm: 'right' },\n }}\n >\n <button onClick={() => handleCopyLink(reply.id)}>\n <IconSvg icon=\"link\" label={'Copy link to this reply'} />\n </button>\n {isCurrentUserAuthor && (\n <button onClick={() => setShowReplyModal(true)}>\n <IconSvg icon=\"edit\" label={'Edit reply'} />\n </button>\n )}\n {(entityBundle?.permissions.canModerate ||\n isForumModerator) && (\n <button onClick={() => setShowDeleteModal(true)}>\n <IconSvg icon=\"delete\" label={'Delete reply'} />\n </button>\n )}\n </Box>\n </div>\n </div>\n <ForumThreadEditor\n isReply={true}\n initialText={message}\n onClose={() => setShowReplyModal(false)}\n id={reply.id}\n isDialog={true}\n openDialog={showReplyModal}\n />\n <WarningDialog\n open={showDeleteModal}\n title=\"Confirm Deletion\"\n content=\"Are you sure you want to delete this reply?\"\n onCancel={() => {\n setShowDeleteModal(false)\n }}\n onConfirm={() =>\n deleteReply({\n forumId: reply.forumId,\n threadId: reply.threadId,\n replyId: reply.id,\n })\n }\n confirmButtonColor=\"error\"\n confirmButtonText=\"Delete\"\n />\n </>\n )}\n </>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
@@ -1,6 +1,7 @@
1
1
  export type DiscussionThreadProps = {
2
2
  threadId: string;
3
3
  limit: number;
4
+ emptyBodyContent?: string;
4
5
  };
5
6
  export declare function DiscussionThread(props: DiscussionThreadProps): import("react/jsx-runtime").JSX.Element;
6
7
  export default DiscussionThread;
@@ -1 +1 @@
1
- {"version":3,"file":"DiscussionThread.d.ts","sourceRoot":"","sources":["../../../src/components/Forum/DiscussionThread.tsx"],"names":[],"mappings":"AAqCA,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAMD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,2CAqV5D;AAED,eAAe,gBAAgB,CAAA"}
1
+ {"version":3,"file":"DiscussionThread.d.ts","sourceRoot":"","sources":["../../../src/components/Forum/DiscussionThread.tsx"],"names":[],"mappings":"AAqCA,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAA;IAChB,KAAK,EAAE,MAAM,CAAA;IACb,gBAAgB,CAAC,EAAE,MAAM,CAAA;CAC1B,CAAA;AAMD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,2CA4V5D;AAED,eAAe,gBAAgB,CAAA"}
@@ -9,10 +9,10 @@ import { WarningDialog as a } from "../SynapseForm/WarningDialog.js";
9
9
  import { formatDate as o } from "../../utils/functions/DateFormatter.js";
10
10
  import { UserBadge as s } from "../UserCard/UserBadge.js";
11
11
  import { useGetRepliesInfinite as c } from "../../synapse-queries/forum/useReply.js";
12
- import { useDeleteThread as te, useGetThread as ne, useRestoreThread as re } from "../../synapse-queries/forum/useThread.js";
13
- import { useSubscription as ie } from "../../synapse-queries/subscription/useSubscription.js";
14
- import { ForumThreadEditor as l } from "./ForumThreadEditor.js";
15
- import { REPLY_ID_PARAM_KEY as u } from "./DiscussionConstants.js";
12
+ import { useDeleteThread as l, useGetThread as te, useRestoreThread as ne } from "../../synapse-queries/forum/useThread.js";
13
+ import { useSubscription as re } from "../../synapse-queries/subscription/useSubscription.js";
14
+ import { ForumThreadEditor as u } from "./ForumThreadEditor.js";
15
+ import { REPLY_ID_PARAM_KEY as ie } from "./DiscussionConstants.js";
16
16
  import { DiscussionReply as d } from "./DiscussionReply.js";
17
17
  import { SubscribersModal as f } from "./SubscribersModal.js";
18
18
  import { useGetModerators as p } from "../../synapse-queries/forum/useForum.js";
@@ -25,68 +25,70 @@ import se from "dayjs";
25
25
  //#region src/components/Forum/DiscussionThread.tsx
26
26
  var ce = "You are following this topic. Click to stop following.", le = "You are not following this topic. Click to follow.", D = "Write a reply...";
27
27
  function O(O) {
28
- let { threadId: k, limit: A } = O, j = "16px", [M, N] = g(!0), [P, F] = g(!1), [I, L] = g(!1), [R, z] = g(!1), [B, V] = g(!1), [H, U] = g(!1), [W, G] = g(!1), [ue, de] = g(!1), { threadData: K, threadBody: q, togglePin: fe } = ne(k), { data: J } = r(), { data: pe } = n(K?.projectId ?? "", void 0, ae, { enabled: !!K }), { subscription: Y, toggleSubscribed: me, isLoading: he } = ie(k, E.THREAD), { mutate: ge } = te({ onSuccess: () => {
29
- V(!1), e("A thread has been deleted.", "info");
30
- } }), { mutate: _e } = re({ onSuccess: () => {
28
+ let { threadId: k, limit: A, emptyBodyContent: j } = O, M = "16px", [N, P] = g(!0), [F, I] = g(!1), [L, R] = g(!1), [z, B] = g(!1), [V, H] = g(!1), [U, W] = g(!1), [ue, G] = g(!1), [de, fe] = g(!1), { threadData: K, threadBody: q, togglePin: pe } = te(k), { data: J } = r(), { data: me } = n(K?.projectId ?? "", void 0, ae, { enabled: !!K }), { subscription: Y, toggleSubscribed: he, isLoading: ge } = re(k, E.THREAD), { mutate: _e } = l({ onSuccess: () => {
29
+ H(!1), e("A thread has been deleted.", "info");
30
+ } }), { mutate: ve } = ne({ onSuccess: () => {
31
31
  G(!1), e("A thread has been restored.", "info");
32
- } }), ve = K?.createdBy == J?.ownerId;
33
- function ye() {
34
- if (J?.userName == "anonymous") U(!0);
32
+ } }), ye = K?.createdBy == J?.ownerId;
33
+ function be() {
34
+ if (J?.userName == "anonymous") W(!0);
35
35
  else try {
36
- me();
36
+ he();
37
37
  } catch (t) {
38
38
  e(t.reason, "danger");
39
39
  }
40
40
  }
41
- let { data: X, hasNextPage: be, fetchNextPage: xe } = c(k, M, A), { data: Z } = p(K?.forumId ?? "", { enabled: !!K?.forumId }), Se = Z?.includes(K?.createdBy ?? ""), [Q, Ce] = t(u), $ = h(() => {
41
+ let { data: X, hasNextPage: xe, fetchNextPage: Se } = c(k, N, A), { data: Z } = p(K?.forumId ?? "", { enabled: !!K?.forumId }), Ce = Z?.includes(K?.createdBy ?? ""), [Q, we] = t(ie), $ = h(() => {
42
42
  let e = X?.pages.flatMap((e) => e.results) ?? [];
43
43
  return Q ? e.filter((e) => e.id === Q) : e;
44
- }, [X, Q]);
44
+ }, [X, Q]), Te = () => {
45
+ we(null);
46
+ }, Ee = Z?.includes(J?.ownerId ?? "");
45
47
  return /* @__PURE__ */ T("div", {
46
48
  className: "DiscussionThread",
47
49
  role: "article",
48
50
  children: [
49
- K && q ? /* @__PURE__ */ T(C, { children: [
50
- /* @__PURE__ */ T(_, {
51
- sx: {
52
- mb: 2,
53
- textAlign: "right"
54
- },
55
- children: [/* @__PURE__ */ w(S, {
56
- component: "span",
57
- sx: { mr: 1 },
58
- children: "Sort:"
59
- }), /* @__PURE__ */ T(x, {
60
- color: "primary",
61
- exclusive: !0,
62
- value: M ? "datePosted" : "mostRecent",
63
- children: [/* @__PURE__ */ w(b, {
64
- value: "datePosted",
65
- onClick: () => N(!0),
66
- children: "Date Posted"
67
- }), /* @__PURE__ */ w(b, {
68
- value: "mostRecent",
69
- onClick: () => N(!1),
70
- children: "Most Recent"
71
- })]
51
+ K && /* @__PURE__ */ T(_, {
52
+ sx: {
53
+ mb: 2,
54
+ textAlign: "right"
55
+ },
56
+ children: [/* @__PURE__ */ w(S, {
57
+ component: "span",
58
+ sx: { mr: 1 },
59
+ children: "Sort:"
60
+ }), /* @__PURE__ */ T(x, {
61
+ color: "primary",
62
+ exclusive: !0,
63
+ value: N ? "datePosted" : "mostRecent",
64
+ children: [/* @__PURE__ */ w(b, {
65
+ value: "datePosted",
66
+ onClick: () => P(!0),
67
+ children: "Date Posted"
68
+ }), /* @__PURE__ */ w(b, {
69
+ value: "mostRecent",
70
+ onClick: () => P(!1),
71
+ children: "Most Recent"
72
72
  })]
73
- }),
73
+ })]
74
+ }),
75
+ K && (q !== void 0 || j) ? /* @__PURE__ */ T(C, { children: [
74
76
  /* @__PURE__ */ w(s, {
75
77
  userId: K.createdBy,
76
78
  withAvatar: !0,
77
79
  avatarSize: "MEDIUM",
78
80
  showCardOnHover: !0,
79
- showModeratorBadge: Se
81
+ showModeratorBadge: Ce
80
82
  }),
81
83
  /* @__PURE__ */ T(_, {
82
84
  sx: (e) => ({ [e.breakpoints.down("sm")]: {
83
85
  display: "flex",
84
86
  flexDirection: "column-reverse",
85
- marginBottom: j,
86
- marginTop: j,
87
+ marginBottom: M,
88
+ marginTop: M,
87
89
  ".SubscribersModal": {
88
90
  justifyContent: "flex-start",
89
- marginBottom: j
91
+ marginBottom: M
90
92
  }
91
93
  } }),
92
94
  children: [/* @__PURE__ */ w(S, {
@@ -96,12 +98,12 @@ function O(O) {
96
98
  }), /* @__PURE__ */ w(f, {
97
99
  id: k,
98
100
  objectType: E.THREAD,
99
- showModal: ue,
100
- handleModal: de
101
+ showModal: de,
102
+ handleModal: fe
101
103
  })]
102
104
  }),
103
105
  /* @__PURE__ */ w("div", { children: /* @__PURE__ */ w(ee, {
104
- markdown: q,
106
+ markdown: q || j,
105
107
  objectType: oe.THREAD
106
108
  }) }),
107
109
  /* @__PURE__ */ T("span", { children: [
@@ -109,14 +111,14 @@ function O(O) {
109
111
  o(se(K.createdOn), "M/D/YYYY"),
110
112
  K.isEdited ? /* @__PURE__ */ w("i", { children: " (Edited)" }) : null
111
113
  ] }),
112
- /* @__PURE__ */ w(l, {
114
+ /* @__PURE__ */ w(u, {
113
115
  isReply: !1,
114
116
  initialText: q,
115
- onClose: () => F(!1),
117
+ onClose: () => I(!1),
116
118
  initialTitle: K?.title,
117
119
  id: k,
118
120
  isDialog: !0,
119
- openDialog: P
121
+ openDialog: F
120
122
  })
121
123
  ] }) : /* @__PURE__ */ w(C, {}),
122
124
  /* @__PURE__ */ w(_, {
@@ -137,8 +139,8 @@ function O(O) {
137
139
  /* @__PURE__ */ w("span", { children: /* @__PURE__ */ w("button", {
138
140
  className: "follow-button",
139
141
  "aria-label": Y ? "Unfollow thread" : "Follow thread",
140
- disabled: he,
141
- onClick: () => ye(),
142
+ disabled: ge,
143
+ onClick: () => be(),
142
144
  children: Y ? /* @__PURE__ */ w(i, {
143
145
  icon: "visibility",
144
146
  label: ce
@@ -147,21 +149,21 @@ function O(O) {
147
149
  label: le
148
150
  })
149
151
  }) }),
150
- ve && /* @__PURE__ */ w("button", {
151
- onClick: () => F(!0),
152
+ ye && /* @__PURE__ */ w("button", {
153
+ onClick: () => I(!0),
152
154
  children: /* @__PURE__ */ w(i, {
153
155
  icon: "edit",
154
156
  label: "Edit thread"
155
157
  })
156
158
  }),
157
- pe?.permissions.canModerate ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w("button", {
158
- onClick: () => V(!0),
159
+ me?.permissions.canModerate ? /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w("button", {
160
+ onClick: () => H(!0),
159
161
  children: /* @__PURE__ */ w(i, {
160
162
  icon: "delete",
161
163
  label: "Delete thread"
162
164
  })
163
165
  }), /* @__PURE__ */ w("button", {
164
- onClick: () => fe(),
166
+ onClick: () => pe(),
165
167
  children: K?.isPinned ? /* @__PURE__ */ w(i, {
166
168
  icon: "pushpin",
167
169
  sx: { color: "error.main" },
@@ -178,24 +180,22 @@ function O(O) {
178
180
  mt: 2,
179
181
  mb: 3
180
182
  },
181
- children: I ? /* @__PURE__ */ w(l, {
183
+ children: L ? /* @__PURE__ */ w(u, {
182
184
  id: k,
183
185
  isReply: !0,
184
- onClose: () => L(!1),
186
+ onClose: () => R(!1),
185
187
  isDialog: !1
186
188
  }) : /* @__PURE__ */ w(y, {
187
189
  fullWidth: !0,
188
190
  placeholder: D,
189
191
  onClick: () => {
190
- J?.userName == "anonymous" ? U(!0) : L(!0);
192
+ J?.userName == "anonymous" ? W(!0) : R(!0);
191
193
  }
192
194
  })
193
195
  }),
194
196
  Q && /* @__PURE__ */ T(v, {
195
197
  variant: "outlined",
196
- onClick: () => {
197
- Ce(null);
198
- },
198
+ onClick: Te,
199
199
  sx: {
200
200
  display: "flex",
201
201
  alignItems: "center",
@@ -215,6 +215,7 @@ function O(O) {
215
215
  let t = Z?.includes(e.createdBy);
216
216
  return /* @__PURE__ */ w(d, {
217
217
  reply: e,
218
+ isForumModerator: Ee,
218
219
  isReplyAuthorModerator: t
219
220
  }, e.id);
220
221
  }) }),
@@ -224,47 +225,47 @@ function O(O) {
224
225
  mb: 3,
225
226
  [e.breakpoints.down("sm")]: { MarkdownEditor: { display: "block" } }
226
227
  }),
227
- children: R ? /* @__PURE__ */ w(l, {
228
+ children: z ? /* @__PURE__ */ w(u, {
228
229
  id: k,
229
230
  isReply: !0,
230
- onClose: () => z(!1),
231
+ onClose: () => B(!1),
231
232
  isDialog: !1
232
233
  }) : /* @__PURE__ */ w(y, {
233
234
  fullWidth: !0,
234
235
  placeholder: D,
235
236
  onClick: () => {
236
- J?.userName == "anonymous" ? U(!0) : z(!0);
237
+ J?.userName == "anonymous" ? W(!0) : B(!0);
237
238
  }
238
239
  })
239
240
  }),
240
- be ? /* @__PURE__ */ w(v, {
241
+ xe ? /* @__PURE__ */ w(v, {
241
242
  variant: "outlined",
242
243
  onClick: () => {
243
- xe();
244
+ Se();
244
245
  },
245
246
  children: "Show more results"
246
247
  }) : /* @__PURE__ */ w(C, {}),
247
248
  /* @__PURE__ */ w(a, {
248
- open: B,
249
+ open: V,
249
250
  title: "Confirm Deletion",
250
251
  content: "Are you sure you want to delete this thread?",
251
- onCancel: () => V(!1),
252
- onConfirm: () => K && ge(K),
252
+ onCancel: () => H(!1),
253
+ onConfirm: () => K && _e(K),
253
254
  confirmButtonColor: "error",
254
255
  confirmButtonText: "Delete"
255
256
  }),
256
257
  /* @__PURE__ */ w(a, {
257
- open: W,
258
+ open: ue,
258
259
  title: "Confirm Restoration",
259
260
  content: "Are you sure you want to restore this thread?",
260
261
  onCancel: () => G(!1),
261
- onConfirm: () => K && _e(K),
262
+ onConfirm: () => K && ve(K),
262
263
  confirmButtonColor: "info",
263
264
  confirmButtonText: "Restore"
264
265
  }),
265
266
  /* @__PURE__ */ w(m, {
266
- open: H,
267
- onHide: () => U(!1),
267
+ open: U,
268
+ onHide: () => W(!1),
268
269
  hasCancelButton: !1
269
270
  })
270
271
  ]
@@ -1 +1 @@
1
- {"version":3,"file":"DiscussionThread.js","names":[],"sources":["../../../src/components/Forum/DiscussionThread.tsx"],"sourcesContent":["import { useGetCurrentUserProfile, useGetEntityBundle } from '@/synapse-queries'\nimport { useGetRepliesInfinite } from '@/synapse-queries/forum/useReply'\nimport {\n useDeleteThread,\n useGetThread,\n useRestoreThread,\n} from '@/synapse-queries/forum/useThread'\nimport { useSubscription } from '@/synapse-queries/subscription/useSubscription'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport {\n Box,\n Button,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport {\n ALL_ENTITY_BUNDLE_FIELDS,\n ObjectType,\n SubscriptionObjectType,\n} from '@sage-bionetworks/synapse-types'\nimport dayjs from 'dayjs'\nimport { useMemo, useState } from 'react'\nimport IconSvg from '../IconSvg/IconSvg'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport WarningDialog from '../SynapseForm/WarningDialog'\nimport { displayToast } from '../ToastMessage/ToastMessage'\nimport { UserBadge } from '../UserCard/UserBadge'\nimport { DiscussionReply } from './DiscussionReply'\nimport { ForumThreadEditor } from './ForumThreadEditor'\nimport { SubscribersModal } from './SubscribersModal'\nimport { useGetModerators } from '@/synapse-queries/forum/useForum'\nimport { useNativeSearchParams } from '@/utils/hooks/useNativeSearchParams'\nimport { REPLY_ID_PARAM_KEY } from './DiscussionConstants'\nimport { SignInRequiredModal } from '../SignInRequiredModal/SignInRequiredModal'\n\nexport type DiscussionThreadProps = {\n threadId: string\n limit: number\n}\n\nconst FOLLOWING_TEXT = 'You are following this topic. Click to stop following.'\nconst UNFOLLOWING_TEXT = 'You are not following this topic. Click to follow.'\nconst INPUT_PLACEHOLDER = 'Write a reply...'\n\nexport function DiscussionThread(props: DiscussionThreadProps) {\n const { threadId, limit } = props\n const defaultMargin = '16px'\n\n const [orderByDatePosted, setOrderByDatePosted] = useState(true)\n const [showThreadModal, setShowThreadModal] = useState(false)\n const [showReplyEditor1, setShowReplyEditor1] = useState(false)\n const [showReplyEditor2, setShowReplyEditor2] = useState(false)\n const [showDeleteModal, setShowDeleteModal] = useState(false)\n const [showSignInModal, setShowSignInModal] = useState(false)\n const [showRestoreModal, setShowRestoreModal] = useState(false)\n const [showSubscriberModal, setShowSubscriberModal] = useState(false)\n\n const { threadData, threadBody, togglePin } = useGetThread(threadId)\n const { data: currentUserProfile } = useGetCurrentUserProfile()\n const { data: entityBundle } = useGetEntityBundle(\n threadData?.projectId ?? '',\n undefined,\n ALL_ENTITY_BUNDLE_FIELDS,\n {\n enabled: !!threadData,\n },\n )\n\n const { subscription, toggleSubscribed, isLoading } = useSubscription(\n threadId,\n SubscriptionObjectType.THREAD,\n )\n const { mutate: deleteThread } = useDeleteThread({\n onSuccess: () => {\n setShowDeleteModal(false)\n displayToast('A thread has been deleted.', 'info')\n },\n })\n const { mutate: restoreThread } = useRestoreThread({\n onSuccess: () => {\n setShowRestoreModal(false)\n displayToast('A thread has been restored.', 'info')\n },\n })\n\n const isCurrentUserAuthor =\n threadData?.createdBy == currentUserProfile?.ownerId\n\n function handleFollowBtn() {\n if (currentUserProfile?.userName == 'anonymous') {\n setShowSignInModal(true)\n } else {\n try {\n toggleSubscribed()\n } catch (err: any) {\n displayToast(err.reason as string, 'danger')\n }\n }\n }\n\n const {\n data: replyData,\n hasNextPage,\n fetchNextPage,\n } = useGetRepliesInfinite(threadId, orderByDatePosted, limit)\n\n const { data: moderatorList } = useGetModerators(threadData?.forumId ?? '', {\n enabled: Boolean(threadData?.forumId),\n })\n\n const isAuthorModerator = moderatorList?.includes(threadData?.createdBy ?? '')\n\n const [replyId, setReplyIdParam] = useNativeSearchParams(REPLY_ID_PARAM_KEY)\n\n const replies = useMemo(() => {\n const allReplies = replyData?.pages.flatMap(page => page.results) ?? []\n if (replyId) {\n return allReplies.filter(reply => reply.id === replyId)\n } else {\n return allReplies\n }\n }, [replyData, replyId])\n\n const handleShowAllRepliesButton = () => {\n setReplyIdParam(null)\n }\n\n return (\n <div className=\"DiscussionThread\" role={'article'}>\n {threadData && threadBody ? (\n <>\n <Box sx={{ mb: 2, textAlign: 'right' }}>\n <Typography component={'span'} sx={{ mr: 1 }}>\n Sort:\n </Typography>\n <ToggleButtonGroup\n color={'primary'}\n exclusive\n value={orderByDatePosted ? 'datePosted' : 'mostRecent'}\n >\n <ToggleButton\n value={'datePosted'}\n onClick={() => setOrderByDatePosted(true)}\n >\n Date Posted\n </ToggleButton>\n <ToggleButton\n value={'mostRecent'}\n onClick={() => setOrderByDatePosted(false)}\n >\n Most Recent\n </ToggleButton>\n </ToggleButtonGroup>\n </Box>\n <UserBadge\n userId={threadData.createdBy}\n withAvatar={true}\n avatarSize=\"MEDIUM\"\n showCardOnHover={true}\n showModeratorBadge={isAuthorModerator}\n />\n <Box\n sx={theme => ({\n [theme.breakpoints.down('sm')]: {\n display: 'flex',\n flexDirection: 'column-reverse',\n marginBottom: defaultMargin,\n marginTop: defaultMargin,\n '.SubscribersModal': {\n justifyContent: 'flex-start',\n marginBottom: defaultMargin,\n },\n },\n })}\n >\n <Typography sx={{ marginTop: '4px' }} variant=\"headline2\">\n {threadData.title}\n </Typography>\n <SubscribersModal\n id={threadId}\n objectType={SubscriptionObjectType.THREAD}\n showModal={showSubscriberModal}\n handleModal={setShowSubscriberModal}\n />\n </Box>\n <div>\n <MarkdownSynapse\n markdown={threadBody}\n objectType={ObjectType.THREAD}\n />\n </div>\n <span>\n posted {formatDate(dayjs(threadData.createdOn), 'M/D/YYYY')}\n {threadData.isEdited ? <i>{' (Edited)'}</i> : null}\n </span>\n <ForumThreadEditor\n isReply={false}\n initialText={threadBody}\n onClose={() => setShowThreadModal(false)}\n initialTitle={threadData?.title}\n id={threadId}\n isDialog={true}\n openDialog={showThreadModal}\n />\n </>\n ) : (\n <></>\n )}\n <Box\n sx={{\n float: 'right',\n margin: { xs: '8px 0', sm: '0 24px 0 0' },\n }}\n >\n {threadData?.isDeleted ? (\n <button onClick={() => setShowRestoreModal(true)}>\n <IconSvg icon=\"restore\" label=\"Restore deleted thread\" />\n </button>\n ) : (\n <>\n <span>\n <button\n className=\"follow-button\"\n aria-label={subscription ? 'Unfollow thread' : 'Follow thread'}\n disabled={isLoading}\n onClick={() => handleFollowBtn()}\n >\n {subscription ? (\n <IconSvg icon=\"visibility\" label={FOLLOWING_TEXT} />\n ) : (\n <IconSvg icon=\"visibilityOff\" label={UNFOLLOWING_TEXT} />\n )}\n </button>\n </span>\n {isCurrentUserAuthor && (\n <button onClick={() => setShowThreadModal(true)}>\n <IconSvg icon=\"edit\" label=\"Edit thread\" />\n </button>\n )}\n\n {entityBundle?.permissions.canModerate ? (\n <>\n <button onClick={() => setShowDeleteModal(true)}>\n <IconSvg icon=\"delete\" label=\"Delete thread\" />\n </button>\n <button onClick={() => togglePin()}>\n {threadData?.isPinned ? (\n <IconSvg\n icon=\"pushpin\"\n sx={{ color: 'error.main' }}\n label=\"Unpin thread\"\n />\n ) : (\n <IconSvg icon=\"pushpin\" label=\"Pin thread\" />\n )}\n </button>\n </>\n ) : null}\n </>\n )}\n </Box>\n <Box sx={{ mt: 2, mb: 3 }}>\n {!showReplyEditor1 ? (\n <TextField\n fullWidth\n placeholder={INPUT_PLACEHOLDER}\n onClick={() => {\n if (currentUserProfile?.userName == 'anonymous') {\n setShowSignInModal(true)\n } else {\n setShowReplyEditor1(true)\n }\n }}\n />\n ) : (\n <ForumThreadEditor\n id={threadId}\n isReply={true}\n onClose={() => setShowReplyEditor1(false)}\n isDialog={false}\n />\n )}\n </Box>\n {replyId && (\n <Button\n variant=\"outlined\"\n onClick={handleShowAllRepliesButton}\n sx={{\n display: 'flex',\n alignItems: 'center',\n padding: '2px 8px',\n marginBottom: '12px',\n gap: '4px',\n }}\n >\n <IconSvg icon=\"arrowBack\" sx={{ width: '16px' }} />\n <Typography variant=\"smallText2\">Show all replies</Typography>\n </Button>\n )}\n <div>\n {replies.map(reply => {\n const isReplyAuthorModerator = moderatorList?.includes(\n reply.createdBy,\n )\n return (\n <DiscussionReply\n key={reply.id}\n reply={reply}\n isReplyAuthorModerator={isReplyAuthorModerator}\n />\n )\n })}\n </div>\n {replies.length > 0 && (\n <Box\n sx={theme => ({\n mt: 2,\n mb: 3,\n [theme.breakpoints.down('sm')]: {\n MarkdownEditor: {\n display: 'block',\n },\n },\n })}\n >\n {!showReplyEditor2 ? (\n <TextField\n fullWidth\n placeholder={INPUT_PLACEHOLDER}\n onClick={() => {\n if (currentUserProfile?.userName == 'anonymous') {\n setShowSignInModal(true)\n } else {\n setShowReplyEditor2(true)\n }\n }}\n />\n ) : (\n <ForumThreadEditor\n id={threadId}\n isReply={true}\n onClose={() => setShowReplyEditor2(false)}\n isDialog={false}\n />\n )}\n </Box>\n )}\n\n {hasNextPage ? (\n <Button\n variant=\"outlined\"\n onClick={() => {\n fetchNextPage()\n }}\n >\n Show more results\n </Button>\n ) : (\n <></>\n )}\n <WarningDialog\n open={showDeleteModal}\n title=\"Confirm Deletion\"\n content=\"Are you sure you want to delete this thread?\"\n onCancel={() => setShowDeleteModal(false)}\n onConfirm={() => threadData && deleteThread(threadData)}\n confirmButtonColor=\"error\"\n confirmButtonText=\"Delete\"\n />\n <WarningDialog\n open={showRestoreModal}\n title=\"Confirm Restoration\"\n content=\"Are you sure you want to restore this thread?\"\n onCancel={() => setShowRestoreModal(false)}\n onConfirm={() => threadData && restoreThread(threadData)}\n confirmButtonColor=\"info\"\n confirmButtonText=\"Restore\"\n />\n <SignInRequiredModal\n open={showSignInModal}\n onHide={() => setShowSignInModal(false)}\n hasCancelButton={false}\n />\n </div>\n )\n}\n\nexport default DiscussionThread\n"],"mappings":"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"}
1
+ {"version":3,"file":"DiscussionThread.js","names":[],"sources":["../../../src/components/Forum/DiscussionThread.tsx"],"sourcesContent":["import { useGetCurrentUserProfile, useGetEntityBundle } from '@/synapse-queries'\nimport { useGetRepliesInfinite } from '@/synapse-queries/forum/useReply'\nimport {\n useDeleteThread,\n useGetThread,\n useRestoreThread,\n} from '@/synapse-queries/forum/useThread'\nimport { useSubscription } from '@/synapse-queries/subscription/useSubscription'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport {\n Box,\n Button,\n TextField,\n ToggleButton,\n ToggleButtonGroup,\n Typography,\n} from '@mui/material'\nimport {\n ALL_ENTITY_BUNDLE_FIELDS,\n ObjectType,\n SubscriptionObjectType,\n} from '@sage-bionetworks/synapse-types'\nimport dayjs from 'dayjs'\nimport { useMemo, useState } from 'react'\nimport IconSvg from '../IconSvg/IconSvg'\nimport MarkdownSynapse from '../Markdown/MarkdownSynapse'\nimport WarningDialog from '../SynapseForm/WarningDialog'\nimport { displayToast } from '../ToastMessage/ToastMessage'\nimport { UserBadge } from '../UserCard/UserBadge'\nimport { DiscussionReply } from './DiscussionReply'\nimport { ForumThreadEditor } from './ForumThreadEditor'\nimport { SubscribersModal } from './SubscribersModal'\nimport { useGetModerators } from '@/synapse-queries/forum/useForum'\nimport { useNativeSearchParams } from '@/utils/hooks/useNativeSearchParams'\nimport { REPLY_ID_PARAM_KEY } from './DiscussionConstants'\nimport { SignInRequiredModal } from '../SignInRequiredModal/SignInRequiredModal'\n\nexport type DiscussionThreadProps = {\n threadId: string\n limit: number\n emptyBodyContent?: string\n}\n\nconst FOLLOWING_TEXT = 'You are following this topic. Click to stop following.'\nconst UNFOLLOWING_TEXT = 'You are not following this topic. Click to follow.'\nconst INPUT_PLACEHOLDER = 'Write a reply...'\n\nexport function DiscussionThread(props: DiscussionThreadProps) {\n const { threadId, limit, emptyBodyContent } = props\n const defaultMargin = '16px'\n\n const [orderByDatePosted, setOrderByDatePosted] = useState(true)\n const [showThreadModal, setShowThreadModal] = useState(false)\n const [showReplyEditor1, setShowReplyEditor1] = useState(false)\n const [showReplyEditor2, setShowReplyEditor2] = useState(false)\n const [showDeleteModal, setShowDeleteModal] = useState(false)\n const [showSignInModal, setShowSignInModal] = useState(false)\n const [showRestoreModal, setShowRestoreModal] = useState(false)\n const [showSubscriberModal, setShowSubscriberModal] = useState(false)\n\n const { threadData, threadBody, togglePin } = useGetThread(threadId)\n const { data: currentUserProfile } = useGetCurrentUserProfile()\n const { data: entityBundle } = useGetEntityBundle(\n threadData?.projectId ?? '',\n undefined,\n ALL_ENTITY_BUNDLE_FIELDS,\n {\n enabled: !!threadData,\n },\n )\n\n const { subscription, toggleSubscribed, isLoading } = useSubscription(\n threadId,\n SubscriptionObjectType.THREAD,\n )\n const { mutate: deleteThread } = useDeleteThread({\n onSuccess: () => {\n setShowDeleteModal(false)\n displayToast('A thread has been deleted.', 'info')\n },\n })\n const { mutate: restoreThread } = useRestoreThread({\n onSuccess: () => {\n setShowRestoreModal(false)\n displayToast('A thread has been restored.', 'info')\n },\n })\n\n const isCurrentUserAuthor =\n threadData?.createdBy == currentUserProfile?.ownerId\n\n function handleFollowBtn() {\n if (currentUserProfile?.userName == 'anonymous') {\n setShowSignInModal(true)\n } else {\n try {\n toggleSubscribed()\n } catch (err: any) {\n displayToast(err.reason as string, 'danger')\n }\n }\n }\n\n const {\n data: replyData,\n hasNextPage,\n fetchNextPage,\n } = useGetRepliesInfinite(threadId, orderByDatePosted, limit)\n\n const { data: moderatorList } = useGetModerators(threadData?.forumId ?? '', {\n enabled: Boolean(threadData?.forumId),\n })\n\n const isAuthorModerator = moderatorList?.includes(threadData?.createdBy ?? '')\n\n const [replyId, setReplyIdParam] = useNativeSearchParams(REPLY_ID_PARAM_KEY)\n\n const replies = useMemo(() => {\n const allReplies = replyData?.pages.flatMap(page => page.results) ?? []\n if (replyId) {\n return allReplies.filter(reply => reply.id === replyId)\n } else {\n return allReplies\n }\n }, [replyData, replyId])\n\n const handleShowAllRepliesButton = () => {\n setReplyIdParam(null)\n }\n\n const isForumModerator = moderatorList?.includes(\n currentUserProfile?.ownerId ?? '',\n )\n\n return (\n <div className=\"DiscussionThread\" role={'article'}>\n {threadData && (\n <Box sx={{ mb: 2, textAlign: 'right' }}>\n <Typography component={'span'} sx={{ mr: 1 }}>\n Sort:\n </Typography>\n <ToggleButtonGroup\n color={'primary'}\n exclusive\n value={orderByDatePosted ? 'datePosted' : 'mostRecent'}\n >\n <ToggleButton\n value={'datePosted'}\n onClick={() => setOrderByDatePosted(true)}\n >\n Date Posted\n </ToggleButton>\n <ToggleButton\n value={'mostRecent'}\n onClick={() => setOrderByDatePosted(false)}\n >\n Most Recent\n </ToggleButton>\n </ToggleButtonGroup>\n </Box>\n )}\n {threadData && (threadBody !== undefined || emptyBodyContent) ? (\n <>\n <UserBadge\n userId={threadData.createdBy}\n withAvatar={true}\n avatarSize=\"MEDIUM\"\n showCardOnHover={true}\n showModeratorBadge={isAuthorModerator}\n />\n <Box\n sx={theme => ({\n [theme.breakpoints.down('sm')]: {\n display: 'flex',\n flexDirection: 'column-reverse',\n marginBottom: defaultMargin,\n marginTop: defaultMargin,\n '.SubscribersModal': {\n justifyContent: 'flex-start',\n marginBottom: defaultMargin,\n },\n },\n })}\n >\n <Typography sx={{ marginTop: '4px' }} variant=\"headline2\">\n {threadData.title}\n </Typography>\n <SubscribersModal\n id={threadId}\n objectType={SubscriptionObjectType.THREAD}\n showModal={showSubscriberModal}\n handleModal={setShowSubscriberModal}\n />\n </Box>\n <div>\n <MarkdownSynapse\n markdown={threadBody || emptyBodyContent}\n objectType={ObjectType.THREAD}\n />\n </div>\n <span>\n posted {formatDate(dayjs(threadData.createdOn), 'M/D/YYYY')}\n {threadData.isEdited ? <i>{' (Edited)'}</i> : null}\n </span>\n <ForumThreadEditor\n isReply={false}\n initialText={threadBody}\n onClose={() => setShowThreadModal(false)}\n initialTitle={threadData?.title}\n id={threadId}\n isDialog={true}\n openDialog={showThreadModal}\n />\n </>\n ) : (\n <></>\n )}\n <Box\n sx={{\n float: 'right',\n margin: { xs: '8px 0', sm: '0 24px 0 0' },\n }}\n >\n {threadData?.isDeleted ? (\n <button onClick={() => setShowRestoreModal(true)}>\n <IconSvg icon=\"restore\" label=\"Restore deleted thread\" />\n </button>\n ) : (\n <>\n <span>\n <button\n className=\"follow-button\"\n aria-label={subscription ? 'Unfollow thread' : 'Follow thread'}\n disabled={isLoading}\n onClick={() => handleFollowBtn()}\n >\n {subscription ? (\n <IconSvg icon=\"visibility\" label={FOLLOWING_TEXT} />\n ) : (\n <IconSvg icon=\"visibilityOff\" label={UNFOLLOWING_TEXT} />\n )}\n </button>\n </span>\n {isCurrentUserAuthor && (\n <button onClick={() => setShowThreadModal(true)}>\n <IconSvg icon=\"edit\" label=\"Edit thread\" />\n </button>\n )}\n\n {entityBundle?.permissions.canModerate ? (\n <>\n <button onClick={() => setShowDeleteModal(true)}>\n <IconSvg icon=\"delete\" label=\"Delete thread\" />\n </button>\n <button onClick={() => togglePin()}>\n {threadData?.isPinned ? (\n <IconSvg\n icon=\"pushpin\"\n sx={{ color: 'error.main' }}\n label=\"Unpin thread\"\n />\n ) : (\n <IconSvg icon=\"pushpin\" label=\"Pin thread\" />\n )}\n </button>\n </>\n ) : null}\n </>\n )}\n </Box>\n <Box sx={{ mt: 2, mb: 3 }}>\n {!showReplyEditor1 ? (\n <TextField\n fullWidth\n placeholder={INPUT_PLACEHOLDER}\n onClick={() => {\n if (currentUserProfile?.userName == 'anonymous') {\n setShowSignInModal(true)\n } else {\n setShowReplyEditor1(true)\n }\n }}\n />\n ) : (\n <ForumThreadEditor\n id={threadId}\n isReply={true}\n onClose={() => setShowReplyEditor1(false)}\n isDialog={false}\n />\n )}\n </Box>\n {replyId && (\n <Button\n variant=\"outlined\"\n onClick={handleShowAllRepliesButton}\n sx={{\n display: 'flex',\n alignItems: 'center',\n padding: '2px 8px',\n marginBottom: '12px',\n gap: '4px',\n }}\n >\n <IconSvg icon=\"arrowBack\" sx={{ width: '16px' }} />\n <Typography variant=\"smallText2\">Show all replies</Typography>\n </Button>\n )}\n <div>\n {replies.map(reply => {\n const isReplyAuthorModerator = moderatorList?.includes(\n reply.createdBy,\n )\n return (\n <DiscussionReply\n key={reply.id}\n reply={reply}\n isForumModerator={isForumModerator}\n isReplyAuthorModerator={isReplyAuthorModerator}\n />\n )\n })}\n </div>\n {replies.length > 0 && (\n <Box\n sx={theme => ({\n mt: 2,\n mb: 3,\n [theme.breakpoints.down('sm')]: {\n MarkdownEditor: {\n display: 'block',\n },\n },\n })}\n >\n {!showReplyEditor2 ? (\n <TextField\n fullWidth\n placeholder={INPUT_PLACEHOLDER}\n onClick={() => {\n if (currentUserProfile?.userName == 'anonymous') {\n setShowSignInModal(true)\n } else {\n setShowReplyEditor2(true)\n }\n }}\n />\n ) : (\n <ForumThreadEditor\n id={threadId}\n isReply={true}\n onClose={() => setShowReplyEditor2(false)}\n isDialog={false}\n />\n )}\n </Box>\n )}\n\n {hasNextPage ? (\n <Button\n variant=\"outlined\"\n onClick={() => {\n fetchNextPage()\n }}\n >\n Show more results\n </Button>\n ) : (\n <></>\n )}\n <WarningDialog\n open={showDeleteModal}\n title=\"Confirm Deletion\"\n content=\"Are you sure you want to delete this thread?\"\n onCancel={() => setShowDeleteModal(false)}\n onConfirm={() => threadData && deleteThread(threadData)}\n confirmButtonColor=\"error\"\n confirmButtonText=\"Delete\"\n />\n <WarningDialog\n open={showRestoreModal}\n title=\"Confirm Restoration\"\n content=\"Are you sure you want to restore this thread?\"\n onCancel={() => setShowRestoreModal(false)}\n onConfirm={() => threadData && restoreThread(threadData)}\n confirmButtonColor=\"info\"\n confirmButtonText=\"Restore\"\n />\n <SignInRequiredModal\n open={showSignInModal}\n onHide={() => setShowSignInModal(false)}\n hasCancelButton={false}\n />\n </div>\n )\n}\n\nexport default DiscussionThread\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"BioregistryRules.d.ts","sourceRoot":"","sources":["../../../src/components/GenericCard/BioregistryRules.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,gBAAgB;;qBAFL,MAAM;GA+yB7B,CAAA"}
1
+ {"version":3,"file":"BioregistryRules.d.ts","sourceRoot":"","sources":["../../../src/components/GenericCard/BioregistryRules.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,gBAAgB;;qBAFL,MAAM;GAi0B7B,CAAA"}
@@ -481,11 +481,11 @@ var e = (e) => `https://bioregistry.io/${e}`, t = [
481
481
  onMatch: e
482
482
  },
483
483
  {
484
- regex: /(mesh:(?:C|D|M)\d{6,9})/,
484
+ regex: /(mesh:(?:C|D|Q)\d+)/,
485
485
  onMatch: e
486
486
  },
487
487
  {
488
- regex: /(metabolights:MTBLS\d+)/,
488
+ regex: /(metabolights:MTBL[CS]\d+)/,
489
489
  onMatch: e
490
490
  },
491
491
  {
@@ -752,6 +752,10 @@ var e = (e) => `https://bioregistry.io/${e}`, t = [
752
752
  regex: /(tcdb:\d+(?:\.[A-Z])?(?:\.\d+)?(?:\.\d+)?(?:\.\d+)?)/,
753
753
  onMatch: e
754
754
  },
755
+ {
756
+ regex: /(tcia.collection:[A-Za-z0-9][A-Za-z0-9_\-\.]*[A-Za-z0-9])/,
757
+ onMatch: e
758
+ },
755
759
  {
756
760
  regex: /(uberon:\d+)/,
757
761
  onMatch: e
@@ -765,7 +769,7 @@ var e = (e) => `https://bioregistry.io/${e}`, t = [
765
769
  onMatch: e
766
770
  },
767
771
  {
768
- regex: /(uniprot:(?:(?:[A-N,R-Z][0-9](?:[A-Z][A-Z, 0-9][A-Z, 0-9][0-9]){1,2})|(?:[O,P,Q][0-9][A-Z, 0-9][A-Z, 0-9][A-Z, 0-9][0-9])(?:\.\d+)?))/,
772
+ regex: /(uniprot:(?:(?:[A-N,R-Z][0-9](?:[A-Z][A-Z, 0-9][A-Z, 0-9][0-9]){1,2})|(?:[O,P,Q][0-9][A-Z, 0-9][A-Z, 0-9][A-Z, 0-9][0-9])(?:\.\d+)?(?:-\d+)?(?:#PRO_\d+)?))/,
769
773
  onMatch: e
770
774
  },
771
775
  {