synapse-react-client 4.0.11 → 4.0.13

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 (137) hide show
  1. package/dist/SWC.index.d.ts +1 -1
  2. package/dist/SWC.index.js +1 -1
  3. package/dist/components/AdaptiveTwoColumnLayout/AdaptiveTwoColumnLayout.d.ts +44 -0
  4. package/dist/components/AdaptiveTwoColumnLayout/AdaptiveTwoColumnLayout.d.ts.map +1 -0
  5. package/dist/components/AdaptiveTwoColumnLayout/AdaptiveTwoColumnLayout.js +46 -0
  6. package/dist/components/AdaptiveTwoColumnLayout/AdaptiveTwoColumnLayout.js.map +1 -0
  7. package/dist/components/DownloadCart/DownloadCartPage.d.ts.map +1 -1
  8. package/dist/components/DownloadCart/DownloadCartPage.js +183 -185
  9. package/dist/components/DownloadCart/DownloadCartPage.js.map +1 -1
  10. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.d.ts.map +1 -1
  11. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js +1 -1
  12. package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
  13. package/dist/components/DraggableDialog/DraggableDialog.js +21 -21
  14. package/dist/components/DraggableDialog/DraggableDialog.js.map +1 -1
  15. package/dist/components/EntityAclEditor/EntityAclEditor.js +8 -8
  16. package/dist/components/EntityAclEditor/EntityAclEditor.js.map +1 -1
  17. package/dist/components/EntityAclEditor/InheritanceMessage.d.ts.map +1 -1
  18. package/dist/components/EntityAclEditor/InheritanceMessage.js +1 -2
  19. package/dist/components/EntityAclEditor/InheritanceMessage.js.map +1 -1
  20. package/dist/components/FullTextSearch/FullTextSearch.d.ts.map +1 -1
  21. package/dist/components/FullTextSearch/FullTextSearch.js +86 -47
  22. package/dist/components/FullTextSearch/FullTextSearch.js.map +1 -1
  23. package/dist/components/GenericCard/TableRowGenericCard.d.ts.map +1 -1
  24. package/dist/components/GenericCard/TableRowGenericCard.js +157 -157
  25. package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
  26. package/dist/components/HeaderCard.d.ts.map +1 -1
  27. package/dist/components/HeaderCard.js +131 -130
  28. package/dist/components/HeaderCard.js.map +1 -1
  29. package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.d.ts +4 -1
  30. package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.d.ts.map +1 -1
  31. package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.js +3 -2
  32. package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.js.map +1 -1
  33. package/dist/components/QueryContext/QueryContext.d.ts +6 -0
  34. package/dist/components/QueryContext/QueryContext.d.ts.map +1 -1
  35. package/dist/components/QueryContext/QueryContext.js.map +1 -1
  36. package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.d.ts.map +1 -1
  37. package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js +12 -11
  38. package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js.map +1 -1
  39. package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.d.ts +5 -0
  40. package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.d.ts.map +1 -1
  41. package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js +32 -29
  42. package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js.map +1 -1
  43. package/dist/components/QueryWrapperPlotNav/UseRowSet.d.ts.map +1 -1
  44. package/dist/components/QueryWrapperPlotNav/UseRowSet.js +4 -1
  45. package/dist/components/QueryWrapperPlotNav/UseRowSet.js.map +1 -1
  46. package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts +59 -0
  47. package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts.map +1 -0
  48. package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js +174 -0
  49. package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js.map +1 -0
  50. package/dist/components/SearchQueryWrapper/SearchQueryWrapper.d.ts +40 -0
  51. package/dist/components/SearchQueryWrapper/SearchQueryWrapper.d.ts.map +1 -0
  52. package/dist/components/SearchQueryWrapper/SearchQueryWrapper.js +100 -0
  53. package/dist/components/SearchQueryWrapper/SearchQueryWrapper.js.map +1 -0
  54. package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.d.ts +56 -0
  55. package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.d.ts.map +1 -0
  56. package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.js +73 -0
  57. package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.js.map +1 -0
  58. package/dist/components/ShareThisPage/ShareThisPage.js +1 -1
  59. package/dist/components/ShareThisPage/ShareThisPage.js.map +1 -1
  60. package/dist/components/SynapseChat/GridAgentChat.d.ts.map +1 -1
  61. package/dist/components/SynapseChat/GridAgentChat.js +20 -14
  62. package/dist/components/SynapseChat/GridAgentChat.js.map +1 -1
  63. package/dist/components/SynapseChat/SynapseChat.d.ts +3 -1
  64. package/dist/components/SynapseChat/SynapseChat.d.ts.map +1 -1
  65. package/dist/components/SynapseChat/SynapseChat.js +51 -36
  66. package/dist/components/SynapseChat/SynapseChat.js.map +1 -1
  67. package/dist/components/SynapseHomepageV2/HotdropsAndNews.css +1 -1
  68. package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.js +8 -7
  69. package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.js.map +1 -1
  70. package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.scss +16 -0
  71. package/dist/components/SynapseHomepageV2/WordPressNews.d.ts +3 -1
  72. package/dist/components/SynapseHomepageV2/WordPressNews.d.ts.map +1 -1
  73. package/dist/components/SynapseHomepageV2/WordPressNews.js +9 -8
  74. package/dist/components/SynapseHomepageV2/WordPressNews.js.map +1 -1
  75. package/dist/components/SynapseHomepageV2/WordPressNewsItem.d.ts +2 -1
  76. package/dist/components/SynapseHomepageV2/WordPressNewsItem.d.ts.map +1 -1
  77. package/dist/components/SynapseHomepageV2/WordPressNewsItem.js +2 -2
  78. package/dist/components/SynapseHomepageV2/WordPressNewsItem.js.map +1 -1
  79. package/dist/components/SynapseTable/SearchV2.d.ts +7 -0
  80. package/dist/components/SynapseTable/SearchV2.d.ts.map +1 -1
  81. package/dist/components/SynapseTable/SearchV2.js.map +1 -1
  82. package/dist/components/SynapseTable/SynapseTableRenderers.d.ts.map +1 -1
  83. package/dist/components/SynapseTable/SynapseTableRenderers.js +1 -1
  84. package/dist/components/SynapseTable/SynapseTableRenderers.js.map +1 -1
  85. package/dist/components/SynapseTable/usePrefetchTableData.d.ts.map +1 -1
  86. package/dist/components/SynapseTable/usePrefetchTableData.js +6 -5
  87. package/dist/components/SynapseTable/usePrefetchTableData.js.map +1 -1
  88. package/dist/components/ToastMessage/ToastMessage.d.ts +1 -1
  89. package/dist/components/ToastMessage/ToastMessage.d.ts.map +1 -1
  90. package/dist/components/ToastMessage/ToastMessage.js +2 -2
  91. package/dist/components/ToastMessage/ToastMessage.js.map +1 -1
  92. package/dist/components/error/ErrorPage.d.ts +0 -4
  93. package/dist/components/error/ErrorPage.d.ts.map +1 -1
  94. package/dist/components/error/ErrorPage.js +25 -30
  95. package/dist/components/error/ErrorPage.js.map +1 -1
  96. package/dist/components/index.d.ts +4 -0
  97. package/dist/components/index.d.ts.map +1 -1
  98. package/dist/components/index.js +41 -39
  99. package/dist/components/widgets/query-filter/FacetFilterControls.d.ts.map +1 -1
  100. package/dist/components/widgets/query-filter/FacetFilterControls.js +2 -2
  101. package/dist/components/widgets/query-filter/FacetFilterControls.js.map +1 -1
  102. package/dist/index.js +52 -50
  103. package/dist/index.js.map +1 -1
  104. package/dist/mocks/entity/index.d.ts.map +1 -1
  105. package/dist/mocks/entity/index.js +18 -16
  106. package/dist/mocks/entity/index.js.map +1 -1
  107. package/dist/mocks/mockSearchQueryData.d.ts +14 -0
  108. package/dist/mocks/mockSearchQueryData.d.ts.map +1 -0
  109. package/dist/mocks/mockSearchQueryData.js +564 -0
  110. package/dist/mocks/mockSearchQueryData.js.map +1 -0
  111. package/dist/mocks/msw/handlers/searchQueryHandlers.d.ts +22 -0
  112. package/dist/mocks/msw/handlers/searchQueryHandlers.d.ts.map +1 -0
  113. package/dist/mocks/msw/handlers/searchQueryHandlers.js +63 -0
  114. package/dist/mocks/msw/handlers/searchQueryHandlers.js.map +1 -0
  115. package/dist/mocks/msw/handlers.d.ts.map +1 -1
  116. package/dist/mocks/msw/handlers.js +9 -7
  117. package/dist/mocks/msw/handlers.js.map +1 -1
  118. package/dist/style/components/_cards.scss +15 -0
  119. package/dist/style/main.css +1 -1
  120. package/dist/synapse-client/SynapseClient.d.ts +7 -1
  121. package/dist/synapse-client/SynapseClient.d.ts.map +1 -1
  122. package/dist/synapse-client/SynapseClient.js +422 -417
  123. package/dist/synapse-client/SynapseClient.js.map +1 -1
  124. package/dist/synapse-client/index.js +3 -3
  125. package/dist/synapse-queries/KeyFactory.d.ts +2 -0
  126. package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
  127. package/dist/synapse-queries/KeyFactory.js +3 -0
  128. package/dist/synapse-queries/KeyFactory.js.map +1 -1
  129. package/dist/tsconfig.build.tsbuildinfo +1 -1
  130. package/dist/utils/APIConstants.d.ts +2 -0
  131. package/dist/utils/APIConstants.d.ts.map +1 -1
  132. package/dist/utils/APIConstants.js +2 -2
  133. package/dist/utils/APIConstants.js.map +1 -1
  134. package/dist/utils/functions/calculateFriendlyFileSize.d.ts.map +1 -1
  135. package/dist/utils/functions/calculateFriendlyFileSize.js +3 -3
  136. package/dist/utils/functions/calculateFriendlyFileSize.js.map +1 -1
  137. package/package.json +3 -3
@@ -10,47 +10,47 @@ import { AccessLevelMenu as o } from "./AccessLevelMenu.js";
10
10
  import { SynapseChatInteraction as s } from "./SynapseChatInteraction.js";
11
11
  import ee from "./SynapseChatMessage.js";
12
12
  import { useEffect as c, useState as l } from "react";
13
- import { Alert as u, Box as d, IconButton as f, List as p, TextField as m, Typography as h, useTheme as g } from "@mui/material";
14
- import { jsx as _, jsxs as v } from "react/jsx-runtime";
15
- import { AgentAccessLevel as y } from "@sage-bionetworks/synapse-types";
16
- import { ArrowUpward as b } from "@mui/icons-material";
13
+ import { Alert as u, Box as d, Chip as f, IconButton as p, List as m, Stack as h, TextField as g, Typography as _, useTheme as te } from "@mui/material";
14
+ import { jsx as v, jsxs as y } from "react/jsx-runtime";
15
+ import { AgentAccessLevel as b } from "@sage-bionetworks/synapse-types";
16
+ import { ArrowUpward as x } from "@mui/icons-material";
17
17
  //#region src/components/SynapseChat/SynapseChat.tsx
18
- function x({ initialMessage: x, agentRegistrationId: S, chatbotName: C = "SynapseChat", hideTitle: w = !1, textboxPositionOffset: T = "0px", sessionContext: E, externalSession: D, setExternalSession: O, externalChatState: k, showAccessLevelMenu: A = !0, onChatResponse: j }) {
19
- let { accessToken: M } = t(), [N, P] = l(), F = D ?? N, I = O ?? P, { mutate: L, error: R } = r({ onSuccess: (e) => I(e) }), { mutate: z } = i({
18
+ function S({ initialMessage: S, agentRegistrationId: C, chatbotName: w = "SynapseChat", hideTitle: ne = !1, textboxPositionOffset: re = "0px", sessionContext: T, externalSession: E, setExternalSession: D, externalChatState: O, showAccessLevelMenu: k = !0, onChatResponse: A, suggestedPrompts: j }) {
19
+ let { accessToken: M } = t(), [N, P] = l(), F = E ?? N, I = D ?? P, { mutate: L, error: R } = r({ onSuccess: (e) => I(e) }), { mutate: z } = i({
20
20
  onSuccess: (e) => I(e),
21
21
  onError: (t) => e(`Unable to update the agent session: ${t.message}`, "danger")
22
- }), B = g(), [V, H] = l(E ? y.WRITE_YOUR_PRIVATE_DATA : y.PUBLICLY_ACCESSIBLE), U = a(F, j), { pendingMessage: W, chatJobIds: G, sendChat: K } = k ?? U, [q, J] = l(""), [Y, X] = l(!1);
22
+ }), B = te(), [V, H] = l(T ? b.WRITE_YOUR_PRIVATE_DATA : b.PUBLICLY_ACCESSIBLE), U = a(F, A), { pendingMessage: W, chatJobIds: G, sendChat: K } = O ?? U, [q, J] = l(""), [Y, X] = l(!1);
23
23
  c(() => {
24
24
  L && !F && L({
25
25
  agentAccessLevel: V,
26
- agentRegistrationId: S,
27
- sessionContext: E
26
+ agentRegistrationId: C,
27
+ sessionContext: T
28
28
  });
29
29
  }, [
30
30
  L,
31
31
  F,
32
32
  M,
33
- E,
33
+ T,
34
34
  V,
35
- S
35
+ C
36
36
  ]), c(() => {
37
- F && x && !Y && (K(x), X(!0));
37
+ F && S && !Y && (K(S), X(!0));
38
38
  }, [
39
39
  F,
40
- x,
40
+ S,
41
41
  Y,
42
42
  K
43
43
  ]);
44
44
  let Z = () => {
45
45
  q.trim() && (K(q.trim()), J(""));
46
- }, Q = !F || !q || !!W, te = (e) => {
46
+ }, Q = !F || !q || !!W, ie = (e) => {
47
47
  !Q && e.key === "Enter" && !e.shiftKey && (e.preventDefault(), Z());
48
48
  }, $ = B.palette.secondary[300];
49
- return R ? /* @__PURE__ */ _(u, {
49
+ return R ? /* @__PURE__ */ v(u, {
50
50
  severity: "error",
51
51
  sx: { my: 2 },
52
52
  children: R.reason
53
- }) : /* @__PURE__ */ v(d, {
53
+ }) : /* @__PURE__ */ y(d, {
54
54
  sx: {
55
55
  display: "flex",
56
56
  flexDirection: "column",
@@ -60,7 +60,7 @@ function x({ initialMessage: x, agentRegistrationId: S, chatbotName: C = "Synaps
60
60
  height: "100%"
61
61
  },
62
62
  children: [
63
- !w && /* @__PURE__ */ _(h, {
63
+ !ne && /* @__PURE__ */ v(_, {
64
64
  variant: "headline1",
65
65
  sx: {
66
66
  p: "20px",
@@ -71,9 +71,9 @@ function x({ initialMessage: x, agentRegistrationId: S, chatbotName: C = "Synaps
71
71
  backgroundColor: "white",
72
72
  zIndex: 1
73
73
  },
74
- children: C
74
+ children: w
75
75
  }),
76
- A && /* @__PURE__ */ _(o, {
76
+ k && /* @__PURE__ */ v(o, {
77
77
  initAccessLevel: V,
78
78
  onChange: (e) => {
79
79
  H(e), z({
@@ -82,14 +82,14 @@ function x({ initialMessage: x, agentRegistrationId: S, chatbotName: C = "Synaps
82
82
  });
83
83
  }
84
84
  }),
85
- !F && /* @__PURE__ */ _(n, { numRows: 10 }),
86
- F && /* @__PURE__ */ _(d, {
85
+ !F && /* @__PURE__ */ v(n, { numRows: 10 }),
86
+ F && /* @__PURE__ */ v(d, {
87
87
  sx: {
88
88
  flexGrow: 1,
89
89
  overflowY: "auto",
90
90
  mb: 2
91
91
  },
92
- children: /* @__PURE__ */ v(p, {
92
+ children: /* @__PURE__ */ y(m, {
93
93
  sx: {
94
94
  flex: 1,
95
95
  overflowY: "auto",
@@ -97,10 +97,10 @@ function x({ initialMessage: x, agentRegistrationId: S, chatbotName: C = "Synaps
97
97
  display: "flex",
98
98
  flexDirection: "column"
99
99
  },
100
- children: [G.map((e) => /* @__PURE__ */ _(ee, {
100
+ children: [G.map((e) => /* @__PURE__ */ v(ee, {
101
101
  chatJobId: e,
102
102
  onSendChat: K
103
- }, e)), W && /* @__PURE__ */ _(s, {
103
+ }, e)), W && /* @__PURE__ */ v(s, {
104
104
  userMessage: W,
105
105
  chatResponseText: "",
106
106
  chatErrorReason: "",
@@ -109,13 +109,28 @@ function x({ initialMessage: x, agentRegistrationId: S, chatbotName: C = "Synaps
109
109
  })]
110
110
  })
111
111
  }),
112
- /* @__PURE__ */ _(d, {
112
+ /* @__PURE__ */ y(d, {
113
113
  sx: {
114
114
  position: "sticky",
115
- bottom: T,
115
+ bottom: re,
116
116
  backgroundColor: "white"
117
117
  },
118
- children: /* @__PURE__ */ v(d, {
118
+ children: [j && j.length > 0 && G.length === 0 && !W && /* @__PURE__ */ v(h, {
119
+ direction: "row",
120
+ spacing: 1,
121
+ sx: {
122
+ pt: "8px",
123
+ flexWrap: "wrap",
124
+ gap: 1
125
+ },
126
+ children: j.map((e) => /* @__PURE__ */ v(f, {
127
+ label: e,
128
+ variant: "outlined",
129
+ onClick: () => J(e),
130
+ disabled: !F,
131
+ sx: { cursor: "pointer" }
132
+ }, e))
133
+ }), /* @__PURE__ */ y(d, {
119
134
  component: "form",
120
135
  sx: {
121
136
  pt: "8px",
@@ -126,15 +141,15 @@ function x({ initialMessage: x, agentRegistrationId: S, chatbotName: C = "Synaps
126
141
  borderColor: "grey.400"
127
142
  },
128
143
  onSubmit: Z,
129
- children: [/* @__PURE__ */ _(m, {
144
+ children: [/* @__PURE__ */ v(g, {
130
145
  fullWidth: !0,
131
146
  value: q,
132
147
  onChange: (e) => J(e.target.value),
133
- onKeyDown: te,
134
- placeholder: `Message ${C}`,
148
+ onKeyDown: ie,
149
+ placeholder: `Message ${w}`,
135
150
  slotProps: { input: {
136
151
  sx: { borderRadius: 96.6 },
137
- endAdornment: /* @__PURE__ */ _(f, {
152
+ endAdornment: /* @__PURE__ */ v(p, {
138
153
  disabled: Q,
139
154
  onClick: Z,
140
155
  sx: {
@@ -145,23 +160,23 @@ function x({ initialMessage: x, agentRegistrationId: S, chatbotName: C = "Synaps
145
160
  borderWidth: Q ? "1px" : "2px",
146
161
  borderColor: Q ? "gray" : $
147
162
  },
148
- children: /* @__PURE__ */ _(b, {})
163
+ children: /* @__PURE__ */ v(x, {})
149
164
  })
150
165
  } }
151
- }), /* @__PURE__ */ v(h, {
166
+ }), /* @__PURE__ */ y(_, {
152
167
  variant: "smallText1",
153
168
  sx: {
154
169
  pt: "8px",
155
170
  textAlign: "center"
156
171
  },
157
- children: [C, " can make mistakes."]
172
+ children: [w, " can make mistakes."]
158
173
  })]
159
- })
174
+ })]
160
175
  })
161
176
  ]
162
177
  });
163
178
  }
164
179
  //#endregion
165
- export { x as SynapseChat, x as default };
180
+ export { S as SynapseChat, S as default };
166
181
 
167
182
  //# sourceMappingURL=SynapseChat.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SynapseChat.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChat.tsx"],"sourcesContent":["import { ChatState, useChatState } from '@/components/SynapseChat/useChatState'\nimport {\n useCreateAgentSession,\n useUpdateAgentSession,\n} from '@/synapse-queries/chat/useChat'\nimport { useSynapseContext } from '@/utils'\nimport { ArrowUpward } from '@mui/icons-material'\nimport {\n Alert,\n Box,\n IconButton,\n List,\n TextField,\n Typography,\n useTheme,\n} from '@mui/material'\nimport { Color } from '@mui/material/styles'\nimport { GridAgentSessionContext } from '@sage-bionetworks/synapse-client'\nimport {\n AgentAccessLevel,\n AgentSession,\n TraceEvent,\n} from '@sage-bionetworks/synapse-types'\nimport { KeyboardEventHandler, useEffect, useState } from 'react'\nimport { SkeletonParagraph } from '../Skeleton'\nimport { displayToast } from '../ToastMessage'\nimport AccessLevelMenu from './AccessLevelMenu'\nimport SynapseChatInteraction from './SynapseChatInteraction'\nimport SynapseChatMessage from './SynapseChatMessage'\n\nexport type SynapseChatProps = {\n initialMessage?: string //optional initial message\n agentRegistrationId?: string // if provided, use this agent\n chatbotName?: string // optional name of this chatbot agent\n hideTitle?: boolean\n textboxPositionOffset?: string // when embedded in a form, the textbox (form) stuck to the bottom may need to be offset due to container padding (dialog content for example!)\n /* optional session context for the agent session */\n sessionContext?: GridAgentSessionContext\n /* The current session, if state is lifted out of this component */\n externalSession?: AgentSession\n /* A callback invoked to bootstrap the current session, if state is to be lifted out of this component */\n setExternalSession?: (s: AgentSession | undefined) => void\n /* The current chat history, if state is lifted out of this component */\n externalChatState?: ChatState\n // default access level for the agent session.\n defaultAgentAccessLevel?: AgentAccessLevel\n // Whether to show the access level menu for the agent session.\n showAccessLevelMenu?: boolean\n /**\n * Optional callback invoked once when a chat response is received from the server.\n * Use this for side effects such as navigation based on the response content.\n * Called in the mutation onSuccess handler so it runs exactly once per response.\n */\n onChatResponse?: (responseText: string) => void\n}\n\nexport type ChatInteraction = {\n userMessage: string\n chatResponseText?: string\n chatErrorReason?: string\n chatResponseTrace?: TraceEventWithFriendlyMessage[]\n}\n\nexport type TraceEventWithFriendlyMessage = {\n friendlyMessage?: string\n} & TraceEvent\n\nexport function SynapseChat({\n initialMessage,\n agentRegistrationId,\n chatbotName = 'SynapseChat',\n hideTitle = false,\n textboxPositionOffset = '0px',\n sessionContext,\n externalSession,\n setExternalSession,\n externalChatState,\n showAccessLevelMenu = true,\n onChatResponse,\n}: SynapseChatProps) {\n const { accessToken } = useSynapseContext()\n const [localAgentSession, setLocalAgentSession] = useState<AgentSession>()\n const agentSession = externalSession ?? localAgentSession\n const setAgentSession = setExternalSession ?? setLocalAgentSession\n\n const { mutate: createAgentSession, error: createAgentSessionError } =\n useCreateAgentSession({\n onSuccess: newAgentSession => setAgentSession(newAgentSession),\n })\n\n const { mutate: updateAgentSession } = useUpdateAgentSession({\n onSuccess: updatedAgentSession => setAgentSession(updatedAgentSession),\n onError: err =>\n displayToast(\n `Unable to update the agent session: ${err.message}`,\n 'danger',\n ),\n })\n const theme = useTheme()\n const [agentAccessLevel, setAgentAccessLevel] = useState<AgentAccessLevel>(\n sessionContext\n ? AgentAccessLevel.WRITE_YOUR_PRIVATE_DATA\n : AgentAccessLevel.PUBLICLY_ACCESSIBLE,\n )\n\n const internalChatState = useChatState(agentSession, onChatResponse)\n const chatState = externalChatState ?? internalChatState\n const { pendingMessage, chatJobIds, sendChat } = chatState\n\n // Keep track of the text that the user is currently typing into the textfield\n const [userChatTextfieldValue, setUserChatTextfieldValue] = useState('')\n const [initialMessageProcessed, setInitialMessageProcessed] = useState(false)\n\n // Restore chat session history, if exists.\n // TODO: currently only a single page is restored. Add support for multiple pages (and detect the user scrolling up to restore the next page of results older)\n // const {\n // data: sessionHistoryInfiniteData,\n // } = //, hasNextPage: hasMoreSessionHistory, fetchNextPage: fetchNextSessionHistoryPage, isLoading: isSessionHistoryLoading } =\n // useGetAgentChatSessionHistoryInfinite(\n // {\n // sessionId: agentSession?.sessionId,\n // },\n // {\n // enabled: !!agentSession,\n // },\n // )\n\n // const sessionHistory = useMemo(\n // () =>\n // sessionHistoryInfiniteData?.pages\n // .flatMap(page => page.page)\n // /* Note: session history is ordered from most recent to least recent in each page, so reverse the order when restoring the chat interface */\n // .reverse() ?? [],\n // [sessionHistoryInfiniteData],\n // )\n\n useEffect(() => {\n // on mount, create a new agent session!\n if (createAgentSession && !agentSession) {\n createAgentSession({\n agentAccessLevel,\n agentRegistrationId,\n sessionContext,\n })\n }\n }, [\n createAgentSession,\n agentSession,\n accessToken,\n sessionContext,\n agentAccessLevel,\n agentRegistrationId,\n ])\n\n useEffect(() => {\n // on mount, resolve the initial message chat interaction (if set)\n if (agentSession && initialMessage && !initialMessageProcessed) {\n sendChat(initialMessage)\n setInitialMessageProcessed(true)\n }\n }, [agentSession, initialMessage, initialMessageProcessed, sendChat])\n\n const handleSendMessage = () => {\n if (userChatTextfieldValue.trim()) {\n sendChat(userChatTextfieldValue.trim())\n setUserChatTextfieldValue('')\n }\n }\n\n const isDisabled =\n !agentSession || !userChatTextfieldValue || !!pendingMessage\n\n const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = event => {\n if (!isDisabled && event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault()\n handleSendMessage()\n }\n }\n\n const sendMessageButtonColor = (\n theme.palette.secondary as unknown as Color\n )[300]\n if (createAgentSessionError) {\n return (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {createAgentSessionError.reason}\n </Alert>\n )\n }\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n maxWidth: '1100px',\n mx: 'auto',\n height: '100%',\n }}\n >\n {!hideTitle && (\n <Typography\n variant=\"headline1\"\n sx={{\n p: '20px',\n borderBottom: '1px solid',\n borderColor: 'grey.300',\n position: 'sticky',\n top: '0px',\n backgroundColor: 'white',\n zIndex: 1,\n }}\n >\n {chatbotName}\n </Typography>\n )}\n {showAccessLevelMenu && (\n <AccessLevelMenu\n initAccessLevel={agentAccessLevel}\n onChange={newAccessLevel => {\n setAgentAccessLevel(newAccessLevel)\n updateAgentSession({\n agentAccessLevel: newAccessLevel,\n sessionId: agentSession!.sessionId,\n })\n }}\n />\n )}\n {!agentSession && <SkeletonParagraph numRows={10} />}\n {agentSession && (\n <Box sx={{ flexGrow: 1, overflowY: 'auto', mb: 2 }}>\n <List\n sx={{\n flex: 1,\n overflowY: 'auto',\n pt: '20px',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {/* {sessionHistory &&\n sessionHistory.map((interaction, index) => {\n return (\n <SynapseChatInteraction\n key={index}\n userMessage={interaction.usersRequestText}\n chatResponseText={interaction.agentResponseText}\n />\n )\n })} */}\n {chatJobIds.map(jobId => {\n return (\n <SynapseChatMessage\n key={jobId}\n chatJobId={jobId}\n onSendChat={sendChat}\n />\n )\n })}\n {pendingMessage && (\n <SynapseChatInteraction\n userMessage={pendingMessage}\n chatResponseText={''}\n chatErrorReason={''}\n scrollIntoView\n onSendChat={sendChat}\n />\n )}\n </List>\n </Box>\n )}\n <Box\n sx={{\n position: 'sticky',\n bottom: textboxPositionOffset,\n backgroundColor: 'white',\n }}\n >\n <Box\n component=\"form\"\n sx={{\n pt: '8px',\n mt: '5px',\n pb: '10px',\n position: 'sticky',\n borderTop: '1px solid',\n borderColor: 'grey.400',\n }}\n onSubmit={handleSendMessage}\n >\n <TextField\n fullWidth\n value={userChatTextfieldValue}\n onChange={e => setUserChatTextfieldValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={`Message ${chatbotName}`}\n slotProps={{\n input: {\n sx: { borderRadius: 96.6 },\n endAdornment: (\n <IconButton\n disabled={isDisabled}\n onClick={handleSendMessage}\n sx={{\n ml: '7px',\n mr: '-8px',\n color: sendMessageButtonColor,\n borderStyle: 'solid',\n borderWidth: isDisabled ? '1px' : '2px',\n borderColor: isDisabled ? 'gray' : sendMessageButtonColor,\n }}\n >\n <ArrowUpward />\n </IconButton>\n ),\n },\n }}\n />\n <Typography\n variant=\"smallText1\"\n sx={{ pt: '8px', textAlign: 'center' }}\n >\n {chatbotName} can make mistakes.\n </Typography>\n </Box>\n </Box>\n </Box>\n )\n}\n\nexport default SynapseChat\n"],"mappings":"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"}
1
+ {"version":3,"file":"SynapseChat.js","names":[],"sources":["../../../src/components/SynapseChat/SynapseChat.tsx"],"sourcesContent":["import { ChatState, useChatState } from '@/components/SynapseChat/useChatState'\nimport {\n useCreateAgentSession,\n useUpdateAgentSession,\n} from '@/synapse-queries/chat/useChat'\nimport { useSynapseContext } from '@/utils'\nimport { ArrowUpward } from '@mui/icons-material'\nimport {\n Alert,\n Box,\n Chip,\n IconButton,\n List,\n Stack,\n TextField,\n Typography,\n useTheme,\n} from '@mui/material'\nimport { Color } from '@mui/material/styles'\nimport { GridAgentSessionContext } from '@sage-bionetworks/synapse-client'\nimport {\n AgentAccessLevel,\n AgentSession,\n TraceEvent,\n} from '@sage-bionetworks/synapse-types'\nimport { KeyboardEventHandler, useEffect, useState } from 'react'\nimport { SkeletonParagraph } from '../Skeleton'\nimport { displayToast } from '../ToastMessage'\nimport AccessLevelMenu from './AccessLevelMenu'\nimport SynapseChatInteraction from './SynapseChatInteraction'\nimport SynapseChatMessage from './SynapseChatMessage'\n\nexport type SynapseChatProps = {\n initialMessage?: string //optional initial message\n agentRegistrationId?: string // if provided, use this agent\n chatbotName?: string // optional name of this chatbot agent\n hideTitle?: boolean\n textboxPositionOffset?: string // when embedded in a form, the textbox (form) stuck to the bottom may need to be offset due to container padding (dialog content for example!)\n /* optional session context for the agent session */\n sessionContext?: GridAgentSessionContext\n /* The current session, if state is lifted out of this component */\n externalSession?: AgentSession\n /* A callback invoked to bootstrap the current session, if state is to be lifted out of this component */\n setExternalSession?: (s: AgentSession | undefined) => void\n /* The current chat history, if state is lifted out of this component */\n externalChatState?: ChatState\n // default access level for the agent session.\n defaultAgentAccessLevel?: AgentAccessLevel\n // Whether to show the access level menu for the agent session.\n showAccessLevelMenu?: boolean\n /**\n * Optional callback invoked once when a chat response is received from the server.\n * Use this for side effects such as navigation based on the response content.\n * Called in the mutation onSuccess handler so it runs exactly once per response.\n */\n onChatResponse?: (responseText: string) => void\n /** Optional list of prompt suggestions shown as clickable pills above the text input */\n suggestedPrompts?: string[]\n}\n\nexport type ChatInteraction = {\n userMessage: string\n chatResponseText?: string\n chatErrorReason?: string\n chatResponseTrace?: TraceEventWithFriendlyMessage[]\n}\n\nexport type TraceEventWithFriendlyMessage = {\n friendlyMessage?: string\n} & TraceEvent\n\nexport function SynapseChat({\n initialMessage,\n agentRegistrationId,\n chatbotName = 'SynapseChat',\n hideTitle = false,\n textboxPositionOffset = '0px',\n sessionContext,\n externalSession,\n setExternalSession,\n externalChatState,\n showAccessLevelMenu = true,\n onChatResponse,\n suggestedPrompts,\n}: SynapseChatProps) {\n const { accessToken } = useSynapseContext()\n const [localAgentSession, setLocalAgentSession] = useState<AgentSession>()\n const agentSession = externalSession ?? localAgentSession\n const setAgentSession = setExternalSession ?? setLocalAgentSession\n\n const { mutate: createAgentSession, error: createAgentSessionError } =\n useCreateAgentSession({\n onSuccess: newAgentSession => setAgentSession(newAgentSession),\n })\n\n const { mutate: updateAgentSession } = useUpdateAgentSession({\n onSuccess: updatedAgentSession => setAgentSession(updatedAgentSession),\n onError: err =>\n displayToast(\n `Unable to update the agent session: ${err.message}`,\n 'danger',\n ),\n })\n const theme = useTheme()\n const [agentAccessLevel, setAgentAccessLevel] = useState<AgentAccessLevel>(\n sessionContext\n ? AgentAccessLevel.WRITE_YOUR_PRIVATE_DATA\n : AgentAccessLevel.PUBLICLY_ACCESSIBLE,\n )\n\n const internalChatState = useChatState(agentSession, onChatResponse)\n const chatState = externalChatState ?? internalChatState\n const { pendingMessage, chatJobIds, sendChat } = chatState\n\n // Keep track of the text that the user is currently typing into the textfield\n const [userChatTextfieldValue, setUserChatTextfieldValue] = useState('')\n const [initialMessageProcessed, setInitialMessageProcessed] = useState(false)\n\n // Restore chat session history, if exists.\n // TODO: currently only a single page is restored. Add support for multiple pages (and detect the user scrolling up to restore the next page of results older)\n // const {\n // data: sessionHistoryInfiniteData,\n // } = //, hasNextPage: hasMoreSessionHistory, fetchNextPage: fetchNextSessionHistoryPage, isLoading: isSessionHistoryLoading } =\n // useGetAgentChatSessionHistoryInfinite(\n // {\n // sessionId: agentSession?.sessionId,\n // },\n // {\n // enabled: !!agentSession,\n // },\n // )\n\n // const sessionHistory = useMemo(\n // () =>\n // sessionHistoryInfiniteData?.pages\n // .flatMap(page => page.page)\n // /* Note: session history is ordered from most recent to least recent in each page, so reverse the order when restoring the chat interface */\n // .reverse() ?? [],\n // [sessionHistoryInfiniteData],\n // )\n\n useEffect(() => {\n // on mount, create a new agent session!\n if (createAgentSession && !agentSession) {\n createAgentSession({\n agentAccessLevel,\n agentRegistrationId,\n sessionContext,\n })\n }\n }, [\n createAgentSession,\n agentSession,\n accessToken,\n sessionContext,\n agentAccessLevel,\n agentRegistrationId,\n ])\n\n useEffect(() => {\n // on mount, resolve the initial message chat interaction (if set)\n if (agentSession && initialMessage && !initialMessageProcessed) {\n sendChat(initialMessage)\n setInitialMessageProcessed(true)\n }\n }, [agentSession, initialMessage, initialMessageProcessed, sendChat])\n\n const handleSendMessage = () => {\n if (userChatTextfieldValue.trim()) {\n sendChat(userChatTextfieldValue.trim())\n setUserChatTextfieldValue('')\n }\n }\n\n const isDisabled =\n !agentSession || !userChatTextfieldValue || !!pendingMessage\n\n const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = event => {\n if (!isDisabled && event.key === 'Enter' && !event.shiftKey) {\n event.preventDefault()\n handleSendMessage()\n }\n }\n\n const sendMessageButtonColor = (\n theme.palette.secondary as unknown as Color\n )[300]\n if (createAgentSessionError) {\n return (\n <Alert severity={'error'} sx={{ my: 2 }}>\n {createAgentSessionError.reason}\n </Alert>\n )\n }\n\n return (\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n justifyContent: 'space-between',\n maxWidth: '1100px',\n mx: 'auto',\n height: '100%',\n }}\n >\n {!hideTitle && (\n <Typography\n variant=\"headline1\"\n sx={{\n p: '20px',\n borderBottom: '1px solid',\n borderColor: 'grey.300',\n position: 'sticky',\n top: '0px',\n backgroundColor: 'white',\n zIndex: 1,\n }}\n >\n {chatbotName}\n </Typography>\n )}\n {showAccessLevelMenu && (\n <AccessLevelMenu\n initAccessLevel={agentAccessLevel}\n onChange={newAccessLevel => {\n setAgentAccessLevel(newAccessLevel)\n updateAgentSession({\n agentAccessLevel: newAccessLevel,\n sessionId: agentSession!.sessionId,\n })\n }}\n />\n )}\n {!agentSession && <SkeletonParagraph numRows={10} />}\n {agentSession && (\n <Box sx={{ flexGrow: 1, overflowY: 'auto', mb: 2 }}>\n <List\n sx={{\n flex: 1,\n overflowY: 'auto',\n pt: '20px',\n display: 'flex',\n flexDirection: 'column',\n }}\n >\n {/* {sessionHistory &&\n sessionHistory.map((interaction, index) => {\n return (\n <SynapseChatInteraction\n key={index}\n userMessage={interaction.usersRequestText}\n chatResponseText={interaction.agentResponseText}\n />\n )\n })} */}\n {chatJobIds.map(jobId => {\n return (\n <SynapseChatMessage\n key={jobId}\n chatJobId={jobId}\n onSendChat={sendChat}\n />\n )\n })}\n {pendingMessage && (\n <SynapseChatInteraction\n userMessage={pendingMessage}\n chatResponseText={''}\n chatErrorReason={''}\n scrollIntoView\n onSendChat={sendChat}\n />\n )}\n </List>\n </Box>\n )}\n <Box\n sx={{\n position: 'sticky',\n bottom: textboxPositionOffset,\n backgroundColor: 'white',\n }}\n >\n {suggestedPrompts &&\n suggestedPrompts.length > 0 &&\n chatJobIds.length === 0 &&\n !pendingMessage && (\n <Stack\n direction=\"row\"\n spacing={1}\n sx={{ pt: '8px', flexWrap: 'wrap', gap: 1 }}\n >\n {suggestedPrompts.map(prompt => (\n <Chip\n key={prompt}\n label={prompt}\n variant=\"outlined\"\n onClick={() => setUserChatTextfieldValue(prompt)}\n disabled={!agentSession}\n sx={{ cursor: 'pointer' }}\n />\n ))}\n </Stack>\n )}\n <Box\n component=\"form\"\n sx={{\n pt: '8px',\n mt: '5px',\n pb: '10px',\n position: 'sticky',\n borderTop: '1px solid',\n borderColor: 'grey.400',\n }}\n onSubmit={handleSendMessage}\n >\n <TextField\n fullWidth\n value={userChatTextfieldValue}\n onChange={e => setUserChatTextfieldValue(e.target.value)}\n onKeyDown={handleKeyDown}\n placeholder={`Message ${chatbotName}`}\n slotProps={{\n input: {\n sx: { borderRadius: 96.6 },\n endAdornment: (\n <IconButton\n disabled={isDisabled}\n onClick={handleSendMessage}\n sx={{\n ml: '7px',\n mr: '-8px',\n color: sendMessageButtonColor,\n borderStyle: 'solid',\n borderWidth: isDisabled ? '1px' : '2px',\n borderColor: isDisabled ? 'gray' : sendMessageButtonColor,\n }}\n >\n <ArrowUpward />\n </IconButton>\n ),\n },\n }}\n />\n <Typography\n variant=\"smallText1\"\n sx={{ pt: '8px', textAlign: 'center' }}\n >\n {chatbotName} can make mistakes.\n </Typography>\n </Box>\n </Box>\n </Box>\n )\n}\n\nexport default SynapseChat\n"],"mappings":"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"}
@@ -1 +1 @@
1
- ._container_4ch9y_1{background-color:#fff3;border-radius:9px;grid-template-columns:100%;justify-items:start;max-width:1300px;margin:auto;padding-top:0;padding-bottom:40px;display:grid}@media (width>=600px){._container_4ch9y_1{grid-template-columns:50% 50%;padding-top:80px;padding-bottom:60px}}._item_4ch9y_20{border-right:1px solid var(--synapse-gray-400);border-bottom:1px solid var(--synapse-gray-400);border-left:1px solid var(--synapse-gray-400);grid-template-columns:80% 20%;display:grid}._item_4ch9y_20:first-child{border-top:1px solid var(--synapse-gray-400)}@media (width>=600px){._item_4ch9y_20{border-top:none;border-left:none}._item_4ch9y_20:nth-child(odd){border-left:1px solid var(--synapse-gray-400)}._item_4ch9y_20:nth-child(-n+2){border-top:1px solid var(--synapse-gray-400)}}._item_4ch9y_20{background-color:#ffffffe6;width:100%;padding:15px 0;text-decoration:none}._item_4ch9y_20:hover{cursor:pointer;background-color:#e9f3fef2;text-decoration:none!important}._item_4ch9y_20 ._itemTitle_4ch9y_53{color:var(--synapse-gray-900);font-size:16px;font-weight:700}._item_4ch9y_20 ._itemMeta_4ch9y_58{color:var(--synapse-gray-700)}._itemContent_4ch9y_62{color:var(--synapse-gray-900);padding-left:15px;padding-right:10px}._itemAction_4ch9y_68{place-self:start end;padding-right:15px}._chip_4ch9y_74.MuiChip-root{border-radius:5px;height:24px}
1
+ ._container_1tem6_1{background-color:#fff3;border-radius:9px;grid-template-columns:100%;justify-items:start;max-width:1300px;margin:auto;padding-top:0;padding-bottom:40px;display:grid}@media (width>=600px){._container_1tem6_1{grid-template-columns:50% 50%;padding-top:80px;padding-bottom:60px}}._item_1tem6_20{border-right:1px solid var(--synapse-gray-400);border-bottom:1px solid var(--synapse-gray-400);border-left:1px solid var(--synapse-gray-400);grid-template-columns:80% 20%;display:grid}._item_1tem6_20:first-child{border-top:1px solid var(--synapse-gray-400)}@media (width>=600px){._item_1tem6_20{border-top:none;border-left:none}._item_1tem6_20:nth-child(odd){border-left:1px solid var(--synapse-gray-400)}._item_1tem6_20:nth-child(-n+2){border-top:1px solid var(--synapse-gray-400)}}._item_1tem6_20{background-color:#ffffffe6;width:100%;padding:15px 0;text-decoration:none}._item_1tem6_20:hover{cursor:pointer;background-color:#e9f3fef2;text-decoration:none!important}._item_1tem6_20 ._itemTitle_1tem6_53{color:var(--synapse-gray-900);font-size:16px;font-weight:700}._item_1tem6_20 ._itemMeta_1tem6_58{color:var(--synapse-gray-700)}._adkpVariant_1tem6_62 ._item_1tem6_20:hover{background:linear-gradient(91deg,#7761b7 5.34%,#9067b6 24.31%,#816dc8 91.15%)}._adkpVariant_1tem6_62 ._item_1tem6_20:hover ._itemTitle_1tem6_53,._adkpVariant_1tem6_62 ._item_1tem6_20:hover ._itemMeta_1tem6_58{color:#fff}._itemContent_1tem6_70{color:var(--synapse-gray-900);padding-left:15px;padding-right:10px}._itemAction_1tem6_76{place-self:start end;padding-right:15px}._chip_1tem6_82.MuiChip-root{border-radius:5px;height:24px}
@@ -1,11 +1,12 @@
1
1
  import './HotdropsAndNews.css';var e = {
2
- container: "_container_4ch9y_1",
3
- item: "_item_4ch9y_20",
4
- itemTitle: "_itemTitle_4ch9y_53",
5
- itemMeta: "_itemMeta_4ch9y_58",
6
- itemContent: "_itemContent_4ch9y_62",
7
- itemAction: "_itemAction_4ch9y_68",
8
- chip: "_chip_4ch9y_74"
2
+ container: "_container_1tem6_1",
3
+ item: "_item_1tem6_20",
4
+ itemTitle: "_itemTitle_1tem6_53",
5
+ itemMeta: "_itemMeta_1tem6_58",
6
+ adkpVariant: "_adkpVariant_1tem6_62",
7
+ itemContent: "_itemContent_1tem6_70",
8
+ itemAction: "_itemAction_1tem6_76",
9
+ chip: "_chip_1tem6_82"
9
10
  };
10
11
  //#endregion
11
12
  export { e as default };
@@ -1 +1 @@
1
- {"version":3,"file":"HotdropsAndNews.module.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/HotdropsAndNews.module.scss"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Grid container (SynapseHotDrops / WordPressNews outer wrapper)\n// ---------------------------------------------------------------------------\n\n.container {\n display: grid;\n justify-items: start;\n background-color: rgba(255, 255, 255, 0.2);\n border-radius: 9px;\n max-width: 1300px;\n margin: auto;\n\n // Mobile-first: single column\n grid-template-columns: 100%;\n padding-top: 0;\n padding-bottom: 40px;\n\n // ≥ MUI 'sm' breakpoint (600px)\n @media (min-width: 600px) {\n grid-template-columns: 50% 50%;\n padding-top: 80px;\n padding-bottom: 60px;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Individual item row\n// ---------------------------------------------------------------------------\n\n.item {\n display: grid;\n grid-template-columns: 80% 20%;\n // Each item provides its own right + bottom edge.\n // Leading edges (top/left) are added selectively to avoid doubling.\n border-right: 1px solid var(--synapse-gray-400); // lighter interior border\n border-bottom: 1px solid var(--synapse-gray-400);\n\n // Mobile: single column — every item is the left edge; only the first has a top edge.\n border-left: 1px solid var(--synapse-gray-400);\n &:first-child {\n border-top: 1px solid var(--synapse-gray-400);\n }\n\n // Desktop: two columns — left edge belongs to odd items (col 1); top edge to the first two (row 1).\n @media (min-width: 600px) {\n border-left: none;\n border-top: none;\n\n &:nth-child(odd) {\n border-left: 1px solid var(--synapse-gray-400);\n }\n\n &:nth-child(-n + 2) {\n border-top: 1px solid var(--synapse-gray-400);\n }\n }\n\n width: 100%;\n background-color: rgba(255, 255, 255, 0.9);\n padding: 15px 0;\n\n text-decoration: none;\n\n &:hover {\n background-color: rgba(233, 243, 254, 0.95);\n cursor: pointer;\n text-decoration: none !important;\n }\n\n .itemTitle {\n color: var(--synapse-gray-900);\n font-size: 16px;\n font-weight: 700;\n }\n .itemMeta {\n color: var(--synapse-gray-700);\n }\n}\n\n// ---------------------------------------------------------------------------\n// Item: left content area\n// ---------------------------------------------------------------------------\n\n.itemContent {\n color: var(--synapse-gray-900);\n padding-left: 15px;\n padding-right: 10px;\n}\n\n// ---------------------------------------------------------------------------\n// Item: right action area (chip container)\n// ---------------------------------------------------------------------------\n\n.itemAction {\n justify-self: end;\n align-self: start;\n padding-right: 15px;\n}\n\n// ---------------------------------------------------------------------------\n// Category / type chip\n// ---------------------------------------------------------------------------\n\n.chip:global(.MuiChip-root) {\n border-radius: 5px;\n height: 24px;\n}\n"],"mappings":""}
1
+ {"version":3,"file":"HotdropsAndNews.module.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/HotdropsAndNews.module.scss"],"sourcesContent":["// ---------------------------------------------------------------------------\n// Grid container (SynapseHotDrops / WordPressNews outer wrapper)\n// ---------------------------------------------------------------------------\n\n.container {\n display: grid;\n justify-items: start;\n background-color: rgba(255, 255, 255, 0.2);\n border-radius: 9px;\n max-width: 1300px;\n margin: auto;\n\n // Mobile-first: single column\n grid-template-columns: 100%;\n padding-top: 0;\n padding-bottom: 40px;\n\n // ≥ MUI 'sm' breakpoint (600px)\n @media (min-width: 600px) {\n grid-template-columns: 50% 50%;\n padding-top: 80px;\n padding-bottom: 60px;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Individual item row\n// ---------------------------------------------------------------------------\n\n.item {\n display: grid;\n grid-template-columns: 80% 20%;\n // Each item provides its own right + bottom edge.\n // Leading edges (top/left) are added selectively to avoid doubling.\n border-right: 1px solid var(--synapse-gray-400); // lighter interior border\n border-bottom: 1px solid var(--synapse-gray-400);\n\n // Mobile: single column — every item is the left edge; only the first has a top edge.\n border-left: 1px solid var(--synapse-gray-400);\n &:first-child {\n border-top: 1px solid var(--synapse-gray-400);\n }\n\n // Desktop: two columns — left edge belongs to odd items (col 1); top edge to the first two (row 1).\n @media (min-width: 600px) {\n border-left: none;\n border-top: none;\n\n &:nth-child(odd) {\n border-left: 1px solid var(--synapse-gray-400);\n }\n\n &:nth-child(-n + 2) {\n border-top: 1px solid var(--synapse-gray-400);\n }\n }\n\n width: 100%;\n background-color: rgba(255, 255, 255, 0.9);\n padding: 15px 0;\n\n text-decoration: none;\n\n &:hover {\n background-color: rgba(233, 243, 254, 0.95);\n cursor: pointer;\n text-decoration: none !important;\n }\n\n .itemTitle {\n color: var(--synapse-gray-900);\n font-size: 16px;\n font-weight: 700;\n }\n .itemMeta {\n color: var(--synapse-gray-700);\n }\n}\n\n.adkpVariant {\n .item:hover {\n background: linear-gradient(\n 91deg,\n #7761b7 5.34%,\n #9067b6 24.31%,\n #816dc8 91.15%\n );\n\n .itemTitle,\n .itemMeta {\n color: #fff;\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Item: left content area\n// ---------------------------------------------------------------------------\n\n.itemContent {\n color: var(--synapse-gray-900);\n padding-left: 15px;\n padding-right: 10px;\n}\n\n// ---------------------------------------------------------------------------\n// Item: right action area (chip container)\n// ---------------------------------------------------------------------------\n\n.itemAction {\n justify-self: end;\n align-self: start;\n padding-right: 15px;\n}\n\n// ---------------------------------------------------------------------------\n// Category / type chip\n// ---------------------------------------------------------------------------\n\n.chip:global(.MuiChip-root) {\n border-radius: 5px;\n height: 24px;\n}\n"],"mappings":""}
@@ -77,6 +77,22 @@
77
77
  }
78
78
  }
79
79
 
80
+ .adkpVariant {
81
+ .item:hover {
82
+ background: linear-gradient(
83
+ 91deg,
84
+ #7761b7 5.34%,
85
+ #9067b6 24.31%,
86
+ #816dc8 91.15%
87
+ );
88
+
89
+ .itemTitle,
90
+ .itemMeta {
91
+ color: #fff;
92
+ }
93
+ }
94
+ }
95
+
80
96
  // ---------------------------------------------------------------------------
81
97
  // Item: left content area
82
98
  // ---------------------------------------------------------------------------
@@ -3,6 +3,8 @@ export type WordPressNewsProps = {
3
3
  wordpressSiteUrl: string;
4
4
  /** Number of posts to display. Defaults to 10. */
5
5
  postCount?: number;
6
+ showCategoryChips?: boolean;
7
+ variant?: 'adkp';
6
8
  };
7
- export declare function WordPressNews({ wordpressSiteUrl, postCount, }: WordPressNewsProps): import("react/jsx-runtime").JSX.Element;
9
+ export declare function WordPressNews({ wordpressSiteUrl, postCount, showCategoryChips, variant, }: WordPressNewsProps): import("react/jsx-runtime").JSX.Element;
8
10
  //# sourceMappingURL=WordPressNews.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WordPressNews.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseHomepageV2/WordPressNews.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gFAAgF;IAChF,gBAAgB,EAAE,MAAM,CAAA;IACxB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAgCD,wBAAgB,aAAa,CAAC,EAC5B,gBAAgB,EAChB,SAAc,GACf,EAAE,kBAAkB,2CA8BpB"}
1
+ {"version":3,"file":"WordPressNews.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseHomepageV2/WordPressNews.tsx"],"names":[],"mappings":"AASA,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gFAAgF;IAChF,gBAAgB,EAAE,MAAM,CAAA;IACxB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAgCD,wBAAgB,aAAa,CAAC,EAC5B,gBAAgB,EAChB,SAAc,EACd,iBAAwB,EACxB,OAAO,GACR,EAAE,kBAAkB,2CAoCpB"}
@@ -18,24 +18,25 @@ async function s(e) {
18
18
  if (!n.ok) throw Error(`Failed to fetch WordPress categories: ${n.statusText}`);
19
19
  return n.json();
20
20
  }
21
- function c({ wordpressSiteUrl: c, postCount: l = 10 }) {
22
- let { data: u } = a({
21
+ function c({ wordpressSiteUrl: c, postCount: l = 10, showCategoryChips: u = !0, variant: d }) {
22
+ let { data: f } = a({
23
23
  queryKey: [
24
24
  "wordpressPosts",
25
25
  c,
26
26
  l
27
27
  ],
28
28
  queryFn: () => o(c, l)
29
- }), { data: d } = a({
29
+ }), { data: p } = a({
30
30
  queryKey: ["wordpressCategories", c],
31
31
  queryFn: () => s(c)
32
- }), f = new Map((d ?? []).map((e) => [e.id, e.name]));
33
- return !u || u.length === 0 ? /* @__PURE__ */ i(r, {}) : /* @__PURE__ */ i(n, {
34
- className: e.container,
32
+ }), m = new Map((p ?? []).map((e) => [e.id, e.name]));
33
+ return !f || f.length === 0 ? /* @__PURE__ */ i(r, {}) : /* @__PURE__ */ i(n, {
34
+ className: `${e.container}${d === "adkp" ? ` ${e.adkpVariant}` : ""}`,
35
35
  sx: { color: "primary.100" },
36
- children: u.map((e) => /* @__PURE__ */ i(t, {
36
+ children: f.map((e) => /* @__PURE__ */ i(t, {
37
37
  post: e,
38
- categoryName: f.get(e.categories[0])
38
+ categoryName: m.get(e.categories[0]),
39
+ showCategoryChip: u
39
40
  }, e.id))
40
41
  });
41
42
  }
@@ -1 +1 @@
1
- {"version":3,"file":"WordPressNews.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/WordPressNews.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query'\nimport { Box } from '@mui/material'\nimport {\n WordPressCategory,\n WordPressNewsItem,\n WordPressPost,\n} from './WordPressNewsItem'\nimport styles from './HotdropsAndNews.module.scss'\n\nexport type WordPressNewsProps = {\n /** Base URL of the WordPress site, e.g. \"https://news.adknowledgeportal.org\" */\n wordpressSiteUrl: string\n /** Number of posts to display. Defaults to 10. */\n postCount?: number\n}\n\nasync function fetchWordPressPosts(\n wordpressSiteUrl: string,\n postCount: number,\n): Promise<WordPressPost[]> {\n const url = new URL(`${wordpressSiteUrl}/wp-json/wp/v2/posts`)\n url.searchParams.set('per_page', String(postCount))\n url.searchParams.set('orderby', 'date')\n url.searchParams.set('order', 'desc')\n url.searchParams.set('_fields', 'id,date,link,title,categories')\n const response = await fetch(url.toString())\n if (!response.ok) {\n throw new Error(`Failed to fetch WordPress posts: ${response.statusText}`)\n }\n return response.json() as Promise<WordPressPost[]>\n}\n\nasync function fetchWordPressCategories(\n wordpressSiteUrl: string,\n): Promise<WordPressCategory[]> {\n const url = new URL(`${wordpressSiteUrl}/wp-json/wp/v2/categories`)\n url.searchParams.set('_fields', 'id,name,slug')\n const response = await fetch(url.toString())\n if (!response.ok) {\n throw new Error(\n `Failed to fetch WordPress categories: ${response.statusText}`,\n )\n }\n return response.json() as Promise<WordPressCategory[]>\n}\n\nexport function WordPressNews({\n wordpressSiteUrl,\n postCount = 10,\n}: WordPressNewsProps) {\n const { data: posts } = useQuery({\n queryKey: ['wordpressPosts', wordpressSiteUrl, postCount],\n queryFn: () => fetchWordPressPosts(wordpressSiteUrl, postCount),\n })\n\n const { data: categories } = useQuery({\n queryKey: ['wordpressCategories', wordpressSiteUrl],\n queryFn: () => fetchWordPressCategories(wordpressSiteUrl),\n })\n\n const categoryMap = new Map<number, string>(\n (categories ?? []).map(c => [c.id, c.name]),\n )\n\n if (!posts || posts.length === 0) {\n return <></>\n }\n\n return (\n <Box className={styles.container} sx={{ color: 'primary.100' }}>\n {posts.map(post => (\n <WordPressNewsItem\n key={post.id}\n post={post}\n categoryName={categoryMap.get(post.categories[0])}\n />\n ))}\n </Box>\n )\n}\n"],"mappings":";;;;;;AAgBA,eAAe,EACb,GACA,GAC0B;CAC1B,IAAM,IAAM,IAAI,IAAI,GAAG,EAAiB,sBAAsB;AAI9D,CAHA,EAAI,aAAa,IAAI,YAAY,OAAO,EAAU,CAAC,EACnD,EAAI,aAAa,IAAI,WAAW,OAAO,EACvC,EAAI,aAAa,IAAI,SAAS,OAAO,EACrC,EAAI,aAAa,IAAI,WAAW,gCAAgC;CAChE,IAAM,IAAW,MAAM,MAAM,EAAI,UAAU,CAAC;AAC5C,KAAI,CAAC,EAAS,GACZ,OAAU,MAAM,oCAAoC,EAAS,aAAa;AAE5E,QAAO,EAAS,MAAM;;AAGxB,eAAe,EACb,GAC8B;CAC9B,IAAM,IAAM,IAAI,IAAI,GAAG,EAAiB,2BAA2B;AACnE,GAAI,aAAa,IAAI,WAAW,eAAe;CAC/C,IAAM,IAAW,MAAM,MAAM,EAAI,UAAU,CAAC;AAC5C,KAAI,CAAC,EAAS,GACZ,OAAU,MACR,yCAAyC,EAAS,aACnD;AAEH,QAAO,EAAS,MAAM;;AAGxB,SAAgB,EAAc,EAC5B,qBACA,eAAY,MACS;CACrB,IAAM,EAAE,MAAM,MAAU,EAAS;EAC/B,UAAU;GAAC;GAAkB;GAAkB;GAAU;EACzD,eAAe,EAAoB,GAAkB,EAAU;EAChE,CAAC,EAEI,EAAE,MAAM,MAAe,EAAS;EACpC,UAAU,CAAC,uBAAuB,EAAiB;EACnD,eAAe,EAAyB,EAAiB;EAC1D,CAAC,EAEI,IAAc,IAAI,KACrB,KAAc,EAAE,EAAE,KAAI,MAAK,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAC5C;AAMD,QAJI,CAAC,KAAS,EAAM,WAAW,IACtB,kBAAA,GAAA,EAAK,CAAA,GAIZ,kBAAC,GAAD;EAAK,WAAW,EAAO;EAAW,IAAI,EAAE,OAAO,eAAe;YAC3D,EAAM,KAAI,MACT,kBAAC,GAAD;GAEQ;GACN,cAAc,EAAY,IAAI,EAAK,WAAW,GAAG;GACjD,EAHK,EAAK,GAGV,CACF;EACE,CAAA"}
1
+ {"version":3,"file":"WordPressNews.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/WordPressNews.tsx"],"sourcesContent":["import { useQuery } from '@tanstack/react-query'\nimport { Box } from '@mui/material'\nimport {\n WordPressCategory,\n WordPressNewsItem,\n WordPressPost,\n} from './WordPressNewsItem'\nimport styles from './HotdropsAndNews.module.scss'\n\nexport type WordPressNewsProps = {\n /** Base URL of the WordPress site, e.g. \"https://news.adknowledgeportal.org\" */\n wordpressSiteUrl: string\n /** Number of posts to display. Defaults to 10. */\n postCount?: number\n showCategoryChips?: boolean\n variant?: 'adkp'\n}\n\nasync function fetchWordPressPosts(\n wordpressSiteUrl: string,\n postCount: number,\n): Promise<WordPressPost[]> {\n const url = new URL(`${wordpressSiteUrl}/wp-json/wp/v2/posts`)\n url.searchParams.set('per_page', String(postCount))\n url.searchParams.set('orderby', 'date')\n url.searchParams.set('order', 'desc')\n url.searchParams.set('_fields', 'id,date,link,title,categories')\n const response = await fetch(url.toString())\n if (!response.ok) {\n throw new Error(`Failed to fetch WordPress posts: ${response.statusText}`)\n }\n return response.json() as Promise<WordPressPost[]>\n}\n\nasync function fetchWordPressCategories(\n wordpressSiteUrl: string,\n): Promise<WordPressCategory[]> {\n const url = new URL(`${wordpressSiteUrl}/wp-json/wp/v2/categories`)\n url.searchParams.set('_fields', 'id,name,slug')\n const response = await fetch(url.toString())\n if (!response.ok) {\n throw new Error(\n `Failed to fetch WordPress categories: ${response.statusText}`,\n )\n }\n return response.json() as Promise<WordPressCategory[]>\n}\n\nexport function WordPressNews({\n wordpressSiteUrl,\n postCount = 10,\n showCategoryChips = true,\n variant,\n}: WordPressNewsProps) {\n const { data: posts } = useQuery({\n queryKey: ['wordpressPosts', wordpressSiteUrl, postCount],\n queryFn: () => fetchWordPressPosts(wordpressSiteUrl, postCount),\n })\n\n const { data: categories } = useQuery({\n queryKey: ['wordpressCategories', wordpressSiteUrl],\n queryFn: () => fetchWordPressCategories(wordpressSiteUrl),\n })\n\n const categoryMap = new Map<number, string>(\n (categories ?? []).map(c => [c.id, c.name]),\n )\n\n if (!posts || posts.length === 0) {\n return <></>\n }\n\n return (\n <Box\n className={`${styles.container}${\n variant === 'adkp' ? ` ${styles.adkpVariant}` : ''\n }`}\n sx={{ color: 'primary.100' }}\n >\n {posts.map(post => (\n <WordPressNewsItem\n key={post.id}\n post={post}\n categoryName={categoryMap.get(post.categories[0])}\n showCategoryChip={showCategoryChips}\n />\n ))}\n </Box>\n )\n}\n"],"mappings":";;;;;;AAkBA,eAAe,EACb,GACA,GAC0B;CAC1B,IAAM,IAAM,IAAI,IAAI,GAAG,EAAiB,sBAAsB;AAI9D,CAHA,EAAI,aAAa,IAAI,YAAY,OAAO,EAAU,CAAC,EACnD,EAAI,aAAa,IAAI,WAAW,OAAO,EACvC,EAAI,aAAa,IAAI,SAAS,OAAO,EACrC,EAAI,aAAa,IAAI,WAAW,gCAAgC;CAChE,IAAM,IAAW,MAAM,MAAM,EAAI,UAAU,CAAC;AAC5C,KAAI,CAAC,EAAS,GACZ,OAAU,MAAM,oCAAoC,EAAS,aAAa;AAE5E,QAAO,EAAS,MAAM;;AAGxB,eAAe,EACb,GAC8B;CAC9B,IAAM,IAAM,IAAI,IAAI,GAAG,EAAiB,2BAA2B;AACnE,GAAI,aAAa,IAAI,WAAW,eAAe;CAC/C,IAAM,IAAW,MAAM,MAAM,EAAI,UAAU,CAAC;AAC5C,KAAI,CAAC,EAAS,GACZ,OAAU,MACR,yCAAyC,EAAS,aACnD;AAEH,QAAO,EAAS,MAAM;;AAGxB,SAAgB,EAAc,EAC5B,qBACA,eAAY,IACZ,uBAAoB,IACpB,cACqB;CACrB,IAAM,EAAE,MAAM,MAAU,EAAS;EAC/B,UAAU;GAAC;GAAkB;GAAkB;GAAU;EACzD,eAAe,EAAoB,GAAkB,EAAU;EAChE,CAAC,EAEI,EAAE,MAAM,MAAe,EAAS;EACpC,UAAU,CAAC,uBAAuB,EAAiB;EACnD,eAAe,EAAyB,EAAiB;EAC1D,CAAC,EAEI,IAAc,IAAI,KACrB,KAAc,EAAE,EAAE,KAAI,MAAK,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAC5C;AAMD,QAJI,CAAC,KAAS,EAAM,WAAW,IACtB,kBAAA,GAAA,EAAK,CAAA,GAIZ,kBAAC,GAAD;EACE,WAAW,GAAG,EAAO,YACnB,MAAY,SAAS,IAAI,EAAO,gBAAgB;EAElD,IAAI,EAAE,OAAO,eAAe;YAE3B,EAAM,KAAI,MACT,kBAAC,GAAD;GAEQ;GACN,cAAc,EAAY,IAAI,EAAK,WAAW,GAAG;GACjD,kBAAkB;GAClB,EAJK,EAAK,GAIV,CACF;EACE,CAAA"}
@@ -15,6 +15,7 @@ export type WordPressCategory = {
15
15
  export type WordPressNewsItemProps = {
16
16
  post: WordPressPost;
17
17
  categoryName: string | undefined;
18
+ showCategoryChip?: boolean;
18
19
  };
19
- export declare function WordPressNewsItem({ post, categoryName, }: WordPressNewsItemProps): import("react/jsx-runtime").JSX.Element;
20
+ export declare function WordPressNewsItem({ post, categoryName, showCategoryChip, }: WordPressNewsItemProps): import("react/jsx-runtime").JSX.Element;
20
21
  //# sourceMappingURL=WordPressNewsItem.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"WordPressNewsItem.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseHomepageV2/WordPressNewsItem.tsx"],"names":[],"mappings":"AAOA,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,aAAa,CAAA;IACnB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;CACjC,CAAA;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,GACb,EAAE,sBAAsB,2CA2BxB"}
1
+ {"version":3,"file":"WordPressNewsItem.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseHomepageV2/WordPressNewsItem.tsx"],"names":[],"mappings":"AAOA,MAAM,MAAM,aAAa,GAAG;IAC1B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAA;IAC3B,UAAU,EAAE,MAAM,EAAE,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,IAAI,EAAE,aAAa,CAAA;IACnB,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,CAAA;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,YAAY,EACZ,gBAAuB,GACxB,EAAE,sBAAsB,2CA2BxB"}
@@ -5,7 +5,7 @@ import o from "dayjs";
5
5
  import s from "dayjs/plugin/relativeTime";
6
6
  //#region src/components/SynapseHomepageV2/WordPressNewsItem.tsx
7
7
  o.extend(s);
8
- function c({ post: s, categoryName: c }) {
8
+ function c({ post: s, categoryName: c, showCategoryChip: l = !0 }) {
9
9
  return /* @__PURE__ */ a(t, {
10
10
  component: "a",
11
11
  href: s.link,
@@ -26,7 +26,7 @@ function c({ post: s, categoryName: c }) {
26
26
  })]
27
27
  }), /* @__PURE__ */ i(t, {
28
28
  className: e.itemAction,
29
- children: c && /* @__PURE__ */ i(n, {
29
+ children: c && l && /* @__PURE__ */ i(n, {
30
30
  className: e.chip,
31
31
  label: c,
32
32
  color: "primary"
@@ -1 +1 @@
1
- {"version":3,"file":"WordPressNewsItem.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/WordPressNewsItem.tsx"],"sourcesContent":["import { Box, Chip, Typography } from '@mui/material'\nimport dayjs from 'dayjs'\nimport relativeTime from 'dayjs/plugin/relativeTime'\nimport styles from './HotdropsAndNews.module.scss'\n\ndayjs.extend(relativeTime)\n\nexport type WordPressPost = {\n id: number\n date: string\n link: string\n title: { rendered: string }\n categories: number[]\n}\n\nexport type WordPressCategory = {\n id: number\n name: string\n slug: string\n}\n\nexport type WordPressNewsItemProps = {\n post: WordPressPost\n categoryName: string | undefined\n}\n\nexport function WordPressNewsItem({\n post,\n categoryName,\n}: WordPressNewsItemProps) {\n return (\n <Box\n component=\"a\"\n href={post.link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={styles.item}\n >\n <Box className={styles.itemContent}>\n <Typography\n variant=\"body1\"\n className={styles.itemTitle}\n noWrap\n dangerouslySetInnerHTML={{ __html: post.title.rendered }}\n />\n <Typography variant=\"body1\" className={styles.itemMeta}>\n {dayjs(post.date).fromNow()}\n </Typography>\n </Box>\n <Box className={styles.itemAction}>\n {categoryName && (\n <Chip className={styles.chip} label={categoryName} color=\"primary\" />\n )}\n </Box>\n </Box>\n )\n}\n"],"mappings":";;;;;;AAKA,EAAM,OAAO,EAAa;AAqB1B,SAAgB,EAAkB,EAChC,SACA,mBACyB;AACzB,QACE,kBAAC,GAAD;EACE,WAAU;EACV,MAAM,EAAK;EACX,QAAO;EACP,KAAI;EACJ,WAAW,EAAO;YALpB,CAOE,kBAAC,GAAD;GAAK,WAAW,EAAO;aAAvB,CACE,kBAAC,GAAD;IACE,SAAQ;IACR,WAAW,EAAO;IAClB,QAAA;IACA,yBAAyB,EAAE,QAAQ,EAAK,MAAM,UAAU;IACxD,CAAA,EACF,kBAAC,GAAD;IAAY,SAAQ;IAAQ,WAAW,EAAO;cAC3C,EAAM,EAAK,KAAK,CAAC,SAAS;IAChB,CAAA,CACT;MACN,kBAAC,GAAD;GAAK,WAAW,EAAO;aACpB,KACC,kBAAC,GAAD;IAAM,WAAW,EAAO;IAAM,OAAO;IAAc,OAAM;IAAY,CAAA;GAEnE,CAAA,CACF"}
1
+ {"version":3,"file":"WordPressNewsItem.js","names":[],"sources":["../../../src/components/SynapseHomepageV2/WordPressNewsItem.tsx"],"sourcesContent":["import { Box, Chip, Typography } from '@mui/material'\nimport dayjs from 'dayjs'\nimport relativeTime from 'dayjs/plugin/relativeTime'\nimport styles from './HotdropsAndNews.module.scss'\n\ndayjs.extend(relativeTime)\n\nexport type WordPressPost = {\n id: number\n date: string\n link: string\n title: { rendered: string }\n categories: number[]\n}\n\nexport type WordPressCategory = {\n id: number\n name: string\n slug: string\n}\n\nexport type WordPressNewsItemProps = {\n post: WordPressPost\n categoryName: string | undefined\n showCategoryChip?: boolean\n}\n\nexport function WordPressNewsItem({\n post,\n categoryName,\n showCategoryChip = true,\n}: WordPressNewsItemProps) {\n return (\n <Box\n component=\"a\"\n href={post.link}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className={styles.item}\n >\n <Box className={styles.itemContent}>\n <Typography\n variant=\"body1\"\n className={styles.itemTitle}\n noWrap\n dangerouslySetInnerHTML={{ __html: post.title.rendered }}\n />\n <Typography variant=\"body1\" className={styles.itemMeta}>\n {dayjs(post.date).fromNow()}\n </Typography>\n </Box>\n <Box className={styles.itemAction}>\n {categoryName && showCategoryChip && (\n <Chip className={styles.chip} label={categoryName} color=\"primary\" />\n )}\n </Box>\n </Box>\n )\n}\n"],"mappings":";;;;;;AAKA,EAAM,OAAO,EAAa;AAsB1B,SAAgB,EAAkB,EAChC,SACA,iBACA,sBAAmB,MACM;AACzB,QACE,kBAAC,GAAD;EACE,WAAU;EACV,MAAM,EAAK;EACX,QAAO;EACP,KAAI;EACJ,WAAW,EAAO;YALpB,CAOE,kBAAC,GAAD;GAAK,WAAW,EAAO;aAAvB,CACE,kBAAC,GAAD;IACE,SAAQ;IACR,WAAW,EAAO;IAClB,QAAA;IACA,yBAAyB,EAAE,QAAQ,EAAK,MAAM,UAAU;IACxD,CAAA,EACF,kBAAC,GAAD;IAAY,SAAQ;IAAQ,WAAW,EAAO;cAC3C,EAAM,EAAK,KAAK,CAAC,SAAS;IAChB,CAAA,CACT;MACN,kBAAC,GAAD;GAAK,WAAW,EAAO;aACpB,KAAgB,KACf,kBAAC,GAAD;IAAM,WAAW,EAAO;IAAM,OAAO;IAAc,OAAM;IAAY,CAAA;GAEnE,CAAA,CACF"}
@@ -22,6 +22,13 @@ export type FTSConfig = {
22
22
  textMatchesMode: TextMatchesMode;
23
23
  distance?: number;
24
24
  searchHelpURL?: string;
25
+ /**
26
+ * Optional function to provide autocomplete suggestions for the search bar.
27
+ * When provided, the search input will show a dropdown of suggestions as the user types.
28
+ * @param searchText - The current text in the search input
29
+ * @returns A promise resolving to an array of suggestion strings
30
+ */
31
+ getSuggestions?: (searchText: string) => Promise<string[]>;
25
32
  };
26
33
  export default function Search(props: SearchV2Props): import("react/jsx-runtime").JSX.Element;
27
34
  //# sourceMappingURL=SearchV2.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SearchV2.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseTable/SearchV2.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACb,MAAM,SAAS,CAAA;AAoBhB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAA;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAexC,MAAM,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAA;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,EAAE,gBAAgB,CAAA;IAC9B,yBAAyB,EAAE,6BAA6B,CAAA;IACxD,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,mBAAmB,CAAA;IAChC,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG,SAAS,CAAA;AAC5D,MAAM,MAAM,SAAS,GAAG;IACtB,eAAe,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAA;AA0SD,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,aAAa,2CAGlD"}
1
+ {"version":3,"file":"SearchV2.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseTable/SearchV2.tsx"],"names":[],"mappings":"AAAA,OAAO,EAGL,YAAY,EACb,MAAM,SAAS,CAAA;AAoBhB,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAA;AAClD,OAAO,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAA;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAexC,MAAM,MAAM,mBAAmB,GAAG,MAAM,EAAE,CAAA;AAE1C,MAAM,MAAM,aAAa,GAAG;IAC1B,YAAY,EAAE,gBAAgB,CAAA;IAC9B,yBAAyB,EAAE,6BAA6B,CAAA;IACxD,uBAAuB,CAAC,EAAE,OAAO,CAAA;IACjC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,UAAU,CAAC,EAAE,mBAAmB,CAAA;IAChC,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B;;;;OAIG;IACH,SAAS,CAAC,EAAE,YAAY,CAAC,SAAS,CAAC,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG,kBAAkB,GAAG,SAAS,CAAA;AAC5D,MAAM,MAAM,SAAS,GAAG;IACtB,eAAe,EAAE,eAAe,CAAA;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;CAC3D,CAAA;AA0SD,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,KAAK,EAAE,aAAa,2CAGlD"}
@@ -1 +1 @@
1
- {"version":3,"file":"SearchV2.js","names":[],"sources":["../../../src/components/SynapseTable/SearchV2.tsx"],"sourcesContent":["import {\n isColumnMultiValueFunctionQueryFilter,\n isColumnSingleValueQueryFilter,\n LockedColumn,\n} from '@/utils'\nimport { Collapse } from '@mui/material'\nimport {\n ColumnModel,\n ColumnMultiValueFunction,\n ColumnMultiValueFunctionQueryFilter,\n ColumnSingleValueFilterOperator,\n ColumnSingleValueQueryFilter,\n ColumnTypeEnum,\n QueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport {\n Component,\n createRef,\n FormEvent,\n RefObject,\n SyntheticEvent,\n} from 'react'\nimport { CSSTransition } from 'react-transition-group'\nimport IconSvg from '../IconSvg/IconSvg'\nimport { QueryContextType } from '../QueryContext'\nimport { QueryVisualizationContextType } from '../QueryVisualizationWrapper'\nimport { useGetQueryMetadata } from '../QueryWrapper/useGetQueryMetadata'\nimport { ReadonlyDeep } from 'type-fest'\n\ntype SearchState = {\n show: boolean\n /* \n When the component is revealed in queryplotnav we want to focus on the input field and reveal the dropdown\n there is an issue where the method handleClickOutsideForm will override the state from componentDidUpdate\n so we track when componentDidUpdate just fired so that `show` is not overriden on the click event which\n triggers componentDidUpdate \n */\n didUpdateRanLast: boolean\n searchText: string\n columnName: string\n}\n\nexport type SearchableColumnsV2 = string[]\n\nexport type SearchV2Props = {\n queryContext: QueryContextType\n queryVisualizationContext: QueryVisualizationContextType\n isQueryWrapperMenuChild?: boolean\n defaultColumn?: string\n searchable?: SearchableColumnsV2\n lockedColumn?: LockedColumn\n /**\n * PLFM-8897, PORTALS-3534: Full-Text Search configuration.\n * For Tables that have FTS enabled...\n * If specified, use the specified mode and distance (if BOOLEAN mode). Otherwise default to NATURAL_LANGUAGE mode.\n */\n ftsConfig?: ReadonlyDeep<FTSConfig>\n}\n\nexport type TextMatchesMode = 'NATURAL_LANGUAGE' | 'BOOLEAN'\nexport type FTSConfig = {\n textMatchesMode: TextMatchesMode\n distance?: number // In BOOLEAN mode, this operator tests whether two or more words all start within a specified distance from each other, measured in words.\n searchHelpURL?: string\n}\n\ntype InternalSearchProps = SearchV2Props & {\n columnModels: ColumnModel[] | undefined\n}\n\nclass _Search extends Component<InternalSearchProps, SearchState> {\n public searchFormRef: RefObject<HTMLFormElement | null>\n public radioFormRef: RefObject<HTMLFormElement | null>\n\n constructor(props: InternalSearchProps) {\n super(props)\n this.state = {\n show: false,\n didUpdateRanLast: false,\n searchText: '',\n columnName: this.props.defaultColumn ?? '',\n }\n this.searchFormRef = createRef()\n this.radioFormRef = createRef()\n }\n\n componentDidMount() {\n // @ts-expect-error\n document.addEventListener('click', this.handleClickOutsideForm)\n }\n\n componentDidUpdate(prevProps: InternalSearchProps) {\n if (\n !prevProps.queryVisualizationContext?.showSearchBar &&\n this.props.queryVisualizationContext?.showSearchBar\n ) {\n this.setState({\n show: true,\n didUpdateRanLast: true,\n })\n this.searchFormRef?.current?.querySelector('input')?.focus()\n }\n }\n\n componentWillUnmount() {\n // @ts-expect-error\n document.removeEventListener('click', this.handleClickOutsideForm)\n }\n\n handleClickOutsideForm = (event: SyntheticEvent) => {\n if (\n // @ts-expect-error\n !this.searchFormRef.current?.contains(event?.target) &&\n // @ts-expect-error\n !this.radioFormRef.current?.contains(event?.target)\n ) {\n if (this.state.didUpdateRanLast) {\n this.setState({\n didUpdateRanLast: false,\n })\n } else {\n this.setState({\n show: false,\n })\n }\n }\n }\n\n public search = (event: SyntheticEvent<HTMLFormElement>) => {\n // form completion by default causes the page to reload, so we prevent that\n event.preventDefault()\n const { searchText } = this.state\n let { columnName } = this.state\n const { searchable, lockedColumn } = this.props\n if (columnName === '') {\n if (searchable) {\n // If searchable column names are defined in the config, grab the first one (that is not locked)\n columnName = searchable.filter(\n colName => colName !== lockedColumn?.columnName,\n )[0]\n } else {\n // Otherwise, get the first column model that can be searched.\n // And for study details page: if lockedColumn is defined, remove it from the search\n const searchableColumnModels = this.props.columnModels\n ?.filter(el => el.name !== lockedColumn?.columnName)\n .filter(el => this.isSupportedColumn(el))\n columnName = searchableColumnModels?.[0].name ?? ''\n }\n }\n this.setState({\n show: false,\n })\n const { executeQueryRequest, getCurrentQueryRequest } =\n this.props.queryContext\n\n const lastQueryRequestDeepClone = getCurrentQueryRequest()\n\n const { additionalFilters = [] } = lastQueryRequestDeepClone.query\n\n const indexOfColumn = additionalFilters.findIndex((el: QueryFilter) => {\n if (\n isColumnSingleValueQueryFilter(el) ||\n (isColumnMultiValueFunctionQueryFilter(el) &&\n el.columnName === columnName)\n ) {\n return true\n }\n return false\n })\n if (indexOfColumn === -1) {\n // get the column model to figure out what kind of filter we should apply.\n const columnModel: ColumnModel | undefined =\n this.props.columnModels?.filter(el => el.name === columnName)[0]\n if (columnModel?.columnType.endsWith('_LIST')) {\n const columnMultiValueQueryFilter: ColumnMultiValueFunctionQueryFilter =\n {\n columnName,\n function: ColumnMultiValueFunction.HAS_LIKE,\n _function: ColumnMultiValueFunction.HAS_LIKE,\n values: [`%${searchText}%`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnMultiValueFunctionQueryFilter',\n }\n additionalFilters.push(columnMultiValueQueryFilter)\n } else {\n if (columnModel?.columnType == ColumnTypeEnum.ENTITYID) {\n const columnSingleValueQueryFilter: ColumnSingleValueQueryFilter = {\n columnName,\n operator: ColumnSingleValueFilterOperator.EQUAL,\n values: [`${searchText.toLowerCase().replace('syn', '')}`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnSingleValueQueryFilter',\n }\n additionalFilters.push(columnSingleValueQueryFilter)\n } else {\n const columnSingleValueQueryFilter: ColumnSingleValueQueryFilter = {\n columnName,\n operator: ColumnSingleValueFilterOperator.LIKE,\n values: [`%${searchText}%`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnSingleValueQueryFilter',\n }\n additionalFilters.push(columnSingleValueQueryFilter)\n }\n }\n } else {\n ;(\n additionalFilters[indexOfColumn] as\n | ColumnSingleValueQueryFilter\n | ColumnMultiValueFunctionQueryFilter\n ).values.push(`%${searchText}%`)\n }\n lastQueryRequestDeepClone.query.additionalFilters = additionalFilters\n executeQueryRequest(lastQueryRequestDeepClone)\n }\n\n public handleChange = (event: FormEvent<HTMLInputElement>) => {\n this.setState({\n searchText: event.currentTarget.value,\n })\n }\n\n public isSupportedColumn = (columnModel?: ColumnModel) => {\n switch (columnModel?.columnType) {\n case ColumnTypeEnum.FILEHANDLEID:\n case ColumnTypeEnum.DATE:\n case ColumnTypeEnum.DATE_LIST:\n case ColumnTypeEnum.USERID:\n // case ColumnTypeEnum.ENTITYID: //PORTALS-2995: users may want to search on Synapse ID\n return false\n default:\n return true\n }\n }\n\n public isSupportedColumnAndInProps = (columnModel?: ColumnModel) => {\n if (this.isSupportedColumn(columnModel)) {\n // return true if the searchable array contains this column name\n const { searchable } = this.props\n return searchable?.some(e => e === columnModel?.name)\n }\n return false\n }\n\n render() {\n const {\n searchable,\n lockedColumn,\n columnModels,\n queryVisualizationContext: { showSearchBar, getColumnDisplayName },\n } = this.props\n const { searchText, show, columnName } = this.state\n let searchColumns: string[] = []\n\n // searchable specifies the order of the columns to search\n if (searchable) {\n searchColumns = searchable\n .map(el => columnModels?.find(model => model.name === el))\n .filter(this.isSupportedColumnAndInProps)\n .map(el => el!.name)\n } else if (columnModels) {\n searchColumns = columnModels\n ?.filter(this.isSupportedColumn)\n .map(el => el.name)\n }\n\n // For study details page: if lockedColumn is defined, remove it from the radio dropdown\n if (searchColumns.length && lockedColumn?.columnName) {\n searchColumns = searchColumns.filter(\n el => el !== lockedColumn?.columnName,\n )\n }\n return (\n <div className={`QueryWrapperSearchInput`}>\n <Collapse in={showSearchBar}>\n <form\n className=\"QueryWrapperSearchInput__searchbar\"\n onSubmit={this.search}\n onClick={() => {\n this.setState({ show: true })\n }}\n ref={this.searchFormRef}\n >\n <span className=\"QueryWrapperSearchInput__searchbar__searchicon\">\n <IconSvg icon=\"search\" />\n </span>\n <input\n onChange={this.handleChange}\n onClick={() => {\n this.setState({\n show: true,\n })\n }}\n placeholder=\"Enter Search Terms\"\n value={searchText}\n type=\"text\"\n />\n {this.state.searchText.length > 0 && (\n <button\n className=\"QueryWrapperSearchInput__searchbar__clearbutton\"\n type=\"button\"\n onClick={() => {\n this.setState({\n searchText: '',\n })\n }}\n >\n <IconSvg icon=\"close\" />\n </button>\n )}\n </form>\n </Collapse>\n <div className=\"QueryWrapperSearchInput__dropdown_pos\">\n <CSSTransition\n nodeRef={this.radioFormRef}\n in={show}\n classNames=\"QueryWrapperSearchInput__animate_dropdown\"\n timeout={{ enter: 0, exit: 300 }}\n >\n <form\n ref={this.radioFormRef}\n className=\"QueryWrapperSearchInput__column-select QueryWrapperSearchInput__animate_height\"\n >\n <p className=\"deemphasized\">\n <i> Search In Field: </i>\n </p>\n {searchColumns.map((name, index) => {\n const displayName = getColumnDisplayName(name)\n const isSelected =\n (columnName === '' && index === 0) || columnName === name\n return (\n <div className=\"radio\" key={`search-field-${name}-${index}`}>\n <label>\n <span>\n <input\n id={name}\n type=\"radio\"\n value={name}\n checked={isSelected}\n onClick={() => {\n this.searchFormRef?.current\n ?.querySelector('input')\n ?.focus()\n this.setState({\n columnName: name,\n })\n }}\n />\n <span>{displayName}</span>\n </span>\n </label>\n </div>\n )\n })}\n </form>\n </CSSTransition>\n </div>\n </div>\n )\n }\n}\n\nexport default function Search(props: SearchV2Props) {\n const { data: queryMetadata } = useGetQueryMetadata()\n return <_Search {...props} columnModels={queryMetadata?.columnModels} />\n}\n"],"mappings":";;;;;;;;;;AAsEA,IAAM,IAAN,cAAsB,EAA4C;CAChE;CACA;CAEA,YAAY,GAA4B;AAStC,EARA,MAAM,EAAM,EACZ,KAAK,QAAQ;GACX,MAAM;GACN,kBAAkB;GAClB,YAAY;GACZ,YAAY,KAAK,MAAM,iBAAiB;GACzC,EACD,KAAK,gBAAgB,GAAW,EAChC,KAAK,eAAe,GAAW;;CAGjC,oBAAoB;AAElB,WAAS,iBAAiB,SAAS,KAAK,uBAAuB;;CAGjE,mBAAmB,GAAgC;AACjD,EACE,CAAC,EAAU,2BAA2B,iBACtC,KAAK,MAAM,2BAA2B,kBAEtC,KAAK,SAAS;GACZ,MAAM;GACN,kBAAkB;GACnB,CAAC,EACF,KAAK,eAAe,SAAS,cAAc,QAAQ,EAAE,OAAO;;CAIhE,uBAAuB;AAErB,WAAS,oBAAoB,SAAS,KAAK,uBAAuB;;CAGpE,0BAA0B,MAA0B;AAClD,EAEE,CAAC,KAAK,cAAc,SAAS,SAAS,GAAO,OAAO,IAEpD,CAAC,KAAK,aAAa,SAAS,SAAS,GAAO,OAAO,KAE/C,KAAK,MAAM,mBACb,KAAK,SAAS,EACZ,kBAAkB,IACnB,CAAC,GAEF,KAAK,SAAS,EACZ,MAAM,IACP,CAAC;;CAKR,UAAiB,MAA2C;AAE1D,IAAM,gBAAgB;EACtB,IAAM,EAAE,kBAAe,KAAK,OACxB,EAAE,kBAAe,KAAK,OACpB,EAAE,eAAY,oBAAiB,KAAK;AAgB1C,EAfI,MAAe,OACjB,AAWE,IAXE,IAEW,EAAW,QACtB,MAAW,MAAY,GAAc,WACtC,CAAC,MAI6B,KAAK,MAAM,cACtC,QAAO,MAAM,EAAG,SAAS,GAAc,WAAW,CACnD,QAAO,MAAM,KAAK,kBAAkB,EAAG,CAAC,IACL,GAAG,QAAQ,KAGrD,KAAK,SAAS,EACZ,MAAM,IACP,CAAC;EACF,IAAM,EAAE,wBAAqB,8BAC3B,KAAK,MAAM,cAEP,IAA4B,GAAwB,EAEpD,EAAE,uBAAoB,EAAE,KAAK,EAA0B,OAEvD,IAAgB,EAAkB,WAAW,MACjD,GACE,EAA+B,EAAG,IACjC,EAAsC,EAAG,IACxC,EAAG,eAAe,GAKtB;AACF,MAAI,MAAkB,IAAI;GAExB,IAAM,IACJ,KAAK,MAAM,cAAc,QAAO,MAAM,EAAG,SAAS,EAAW,CAAC;AAChE,OAAI,GAAa,WAAW,SAAS,QAAQ,EAAE;IAC7C,IAAM,IACJ;KACE;KACA,UAAU,EAAyB;KACnC,WAAW,EAAyB;KACpC,QAAQ,CAAC,IAAI,EAAW,GAAG;KAC3B,cACE;KACH;AACH,MAAkB,KAAK,EAA4B;cAE/C,GAAa,cAAc,EAAe,UAAU;IACtD,IAAM,IAA6D;KACjE;KACA,UAAU,EAAgC;KAC1C,QAAQ,CAAC,GAAG,EAAW,aAAa,CAAC,QAAQ,OAAO,GAAG,GAAG;KAC1D,cACE;KACH;AACD,MAAkB,KAAK,EAA6B;UAC/C;IACL,IAAM,IAA6D;KACjE;KACA,UAAU,EAAgC;KAC1C,QAAQ,CAAC,IAAI,EAAW,GAAG;KAC3B,cACE;KACH;AACD,MAAkB,KAAK,EAA6B;;QAKtD,GAAkB,GAGlB,OAAO,KAAK,IAAI,EAAW,GAAG;AAGlC,EADA,EAA0B,MAAM,oBAAoB,GACpD,EAAoB,EAA0B;;CAGhD,gBAAuB,MAAuC;AAC5D,OAAK,SAAS,EACZ,YAAY,EAAM,cAAc,OACjC,CAAC;;CAGJ,qBAA4B,MAA8B;AACxD,UAAQ,GAAa,YAArB;GACE,KAAK,EAAe;GACpB,KAAK,EAAe;GACpB,KAAK,EAAe;GACpB,KAAK,EAAe,OAElB,QAAO;GACT,QACE,QAAO;;;CAIb,+BAAsC,MAA8B;AAClE,MAAI,KAAK,kBAAkB,EAAY,EAAE;GAEvC,IAAM,EAAE,kBAAe,KAAK;AAC5B,UAAO,GAAY,MAAK,MAAK,MAAM,GAAa,KAAK;;AAEvD,SAAO;;CAGT,SAAS;EACP,IAAM,EACJ,eACA,iBACA,iBACA,2BAA2B,EAAE,kBAAe,8BAC1C,KAAK,OACH,EAAE,eAAY,SAAM,kBAAe,KAAK,OAC1C,IAA0B,EAAE;AAoBhC,SAjBI,IACF,IAAgB,EACb,KAAI,MAAM,GAAc,MAAK,MAAS,EAAM,SAAS,EAAG,CAAC,CACzD,OAAO,KAAK,4BAA4B,CACxC,KAAI,MAAM,EAAI,KAAK,GACb,MACT,IAAgB,GACZ,OAAO,KAAK,kBAAkB,CAC/B,KAAI,MAAM,EAAG,KAAK,GAInB,EAAc,UAAU,GAAc,eACxC,IAAgB,EAAc,QAC5B,MAAM,MAAO,GAAc,WAC5B,GAGD,kBAAC,OAAD;GAAK,WAAW;aAAhB,CACE,kBAAC,GAAD;IAAU,IAAI;cACZ,kBAAC,QAAD;KACE,WAAU;KACV,UAAU,KAAK;KACf,eAAe;AACb,WAAK,SAAS,EAAE,MAAM,IAAM,CAAC;;KAE/B,KAAK,KAAK;eANZ;MAQE,kBAAC,QAAD;OAAM,WAAU;iBACd,kBAAC,GAAD,EAAS,MAAK,UAAW,CAAA;OACpB,CAAA;MACP,kBAAC,SAAD;OACE,UAAU,KAAK;OACf,eAAe;AACb,aAAK,SAAS,EACZ,MAAM,IACP,CAAC;;OAEJ,aAAY;OACZ,OAAO;OACP,MAAK;OACL,CAAA;MACD,KAAK,MAAM,WAAW,SAAS,KAC9B,kBAAC,UAAD;OACE,WAAU;OACV,MAAK;OACL,eAAe;AACb,aAAK,SAAS,EACZ,YAAY,IACb,CAAC;;iBAGJ,kBAAC,GAAD,EAAS,MAAK,SAAU,CAAA;OACjB,CAAA;MAEN;;IACE,CAAA,EACX,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,GAAD;KACE,SAAS,KAAK;KACd,IAAI;KACJ,YAAW;KACX,SAAS;MAAE,OAAO;MAAG,MAAM;MAAK;eAEhC,kBAAC,QAAD;MACE,KAAK,KAAK;MACV,WAAU;gBAFZ,CAIE,kBAAC,KAAD;OAAG,WAAU;iBACX,kBAAC,KAAD,EAAA,UAAG,sBAAsB,CAAA;OACvB,CAAA,EACH,EAAc,KAAK,GAAM,MAAU;OAClC,IAAM,IAAc,EAAqB,EAAK;AAG9C,cACE,kBAAC,OAAD;QAAK,WAAU;kBACb,kBAAC,SAAD,EAAA,UACE,kBAAC,QAAD,EAAA,UAAA,CACE,kBAAC,SAAD;SACE,IAAI;SACJ,MAAK;SACL,OAAO;SACP,SATP,MAAe,MAAM,MAAU,KAAM,MAAe;SAU7C,eAAe;AAIb,UAHA,KAAK,eAAe,SAChB,cAAc,QAAQ,EACtB,OAAO,EACX,KAAK,SAAS,EACZ,YAAY,GACb,CAAC;;SAEJ,CAAA,EACF,kBAAC,QAAD,EAAA,UAAO,GAAmB,CAAA,CACrB,EAAA,CAAA,EACD,CAAA;QACJ,EApBsB,gBAAgB,EAAK,GAAG,IAoB9C;QAER,CACG;;KACO,CAAA;IACZ,CAAA,CACF;;;;AAKZ,SAAwB,EAAO,GAAsB;CACnD,IAAM,EAAE,MAAM,MAAkB,GAAqB;AACrD,QAAO,kBAAC,GAAD;EAAS,GAAI;EAAO,cAAc,GAAe;EAAgB,CAAA"}
1
+ {"version":3,"file":"SearchV2.js","names":[],"sources":["../../../src/components/SynapseTable/SearchV2.tsx"],"sourcesContent":["import {\n isColumnMultiValueFunctionQueryFilter,\n isColumnSingleValueQueryFilter,\n LockedColumn,\n} from '@/utils'\nimport { Collapse } from '@mui/material'\nimport {\n ColumnModel,\n ColumnMultiValueFunction,\n ColumnMultiValueFunctionQueryFilter,\n ColumnSingleValueFilterOperator,\n ColumnSingleValueQueryFilter,\n ColumnTypeEnum,\n QueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport {\n Component,\n createRef,\n FormEvent,\n RefObject,\n SyntheticEvent,\n} from 'react'\nimport { CSSTransition } from 'react-transition-group'\nimport IconSvg from '../IconSvg/IconSvg'\nimport { QueryContextType } from '../QueryContext'\nimport { QueryVisualizationContextType } from '../QueryVisualizationWrapper'\nimport { useGetQueryMetadata } from '../QueryWrapper/useGetQueryMetadata'\nimport { ReadonlyDeep } from 'type-fest'\n\ntype SearchState = {\n show: boolean\n /* \n When the component is revealed in queryplotnav we want to focus on the input field and reveal the dropdown\n there is an issue where the method handleClickOutsideForm will override the state from componentDidUpdate\n so we track when componentDidUpdate just fired so that `show` is not overriden on the click event which\n triggers componentDidUpdate \n */\n didUpdateRanLast: boolean\n searchText: string\n columnName: string\n}\n\nexport type SearchableColumnsV2 = string[]\n\nexport type SearchV2Props = {\n queryContext: QueryContextType\n queryVisualizationContext: QueryVisualizationContextType\n isQueryWrapperMenuChild?: boolean\n defaultColumn?: string\n searchable?: SearchableColumnsV2\n lockedColumn?: LockedColumn\n /**\n * PLFM-8897, PORTALS-3534: Full-Text Search configuration.\n * For Tables that have FTS enabled...\n * If specified, use the specified mode and distance (if BOOLEAN mode). Otherwise default to NATURAL_LANGUAGE mode.\n */\n ftsConfig?: ReadonlyDeep<FTSConfig>\n}\n\nexport type TextMatchesMode = 'NATURAL_LANGUAGE' | 'BOOLEAN'\nexport type FTSConfig = {\n textMatchesMode: TextMatchesMode\n distance?: number // In BOOLEAN mode, this operator tests whether two or more words all start within a specified distance from each other, measured in words.\n searchHelpURL?: string\n /**\n * Optional function to provide autocomplete suggestions for the search bar.\n * When provided, the search input will show a dropdown of suggestions as the user types.\n * @param searchText - The current text in the search input\n * @returns A promise resolving to an array of suggestion strings\n */\n getSuggestions?: (searchText: string) => Promise<string[]>\n}\n\ntype InternalSearchProps = SearchV2Props & {\n columnModels: ColumnModel[] | undefined\n}\n\nclass _Search extends Component<InternalSearchProps, SearchState> {\n public searchFormRef: RefObject<HTMLFormElement | null>\n public radioFormRef: RefObject<HTMLFormElement | null>\n\n constructor(props: InternalSearchProps) {\n super(props)\n this.state = {\n show: false,\n didUpdateRanLast: false,\n searchText: '',\n columnName: this.props.defaultColumn ?? '',\n }\n this.searchFormRef = createRef()\n this.radioFormRef = createRef()\n }\n\n componentDidMount() {\n // @ts-expect-error\n document.addEventListener('click', this.handleClickOutsideForm)\n }\n\n componentDidUpdate(prevProps: InternalSearchProps) {\n if (\n !prevProps.queryVisualizationContext?.showSearchBar &&\n this.props.queryVisualizationContext?.showSearchBar\n ) {\n this.setState({\n show: true,\n didUpdateRanLast: true,\n })\n this.searchFormRef?.current?.querySelector('input')?.focus()\n }\n }\n\n componentWillUnmount() {\n // @ts-expect-error\n document.removeEventListener('click', this.handleClickOutsideForm)\n }\n\n handleClickOutsideForm = (event: SyntheticEvent) => {\n if (\n // @ts-expect-error\n !this.searchFormRef.current?.contains(event?.target) &&\n // @ts-expect-error\n !this.radioFormRef.current?.contains(event?.target)\n ) {\n if (this.state.didUpdateRanLast) {\n this.setState({\n didUpdateRanLast: false,\n })\n } else {\n this.setState({\n show: false,\n })\n }\n }\n }\n\n public search = (event: SyntheticEvent<HTMLFormElement>) => {\n // form completion by default causes the page to reload, so we prevent that\n event.preventDefault()\n const { searchText } = this.state\n let { columnName } = this.state\n const { searchable, lockedColumn } = this.props\n if (columnName === '') {\n if (searchable) {\n // If searchable column names are defined in the config, grab the first one (that is not locked)\n columnName = searchable.filter(\n colName => colName !== lockedColumn?.columnName,\n )[0]\n } else {\n // Otherwise, get the first column model that can be searched.\n // And for study details page: if lockedColumn is defined, remove it from the search\n const searchableColumnModels = this.props.columnModels\n ?.filter(el => el.name !== lockedColumn?.columnName)\n .filter(el => this.isSupportedColumn(el))\n columnName = searchableColumnModels?.[0].name ?? ''\n }\n }\n this.setState({\n show: false,\n })\n const { executeQueryRequest, getCurrentQueryRequest } =\n this.props.queryContext\n\n const lastQueryRequestDeepClone = getCurrentQueryRequest()\n\n const { additionalFilters = [] } = lastQueryRequestDeepClone.query\n\n const indexOfColumn = additionalFilters.findIndex((el: QueryFilter) => {\n if (\n isColumnSingleValueQueryFilter(el) ||\n (isColumnMultiValueFunctionQueryFilter(el) &&\n el.columnName === columnName)\n ) {\n return true\n }\n return false\n })\n if (indexOfColumn === -1) {\n // get the column model to figure out what kind of filter we should apply.\n const columnModel: ColumnModel | undefined =\n this.props.columnModels?.filter(el => el.name === columnName)[0]\n if (columnModel?.columnType.endsWith('_LIST')) {\n const columnMultiValueQueryFilter: ColumnMultiValueFunctionQueryFilter =\n {\n columnName,\n function: ColumnMultiValueFunction.HAS_LIKE,\n _function: ColumnMultiValueFunction.HAS_LIKE,\n values: [`%${searchText}%`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnMultiValueFunctionQueryFilter',\n }\n additionalFilters.push(columnMultiValueQueryFilter)\n } else {\n if (columnModel?.columnType == ColumnTypeEnum.ENTITYID) {\n const columnSingleValueQueryFilter: ColumnSingleValueQueryFilter = {\n columnName,\n operator: ColumnSingleValueFilterOperator.EQUAL,\n values: [`${searchText.toLowerCase().replace('syn', '')}`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnSingleValueQueryFilter',\n }\n additionalFilters.push(columnSingleValueQueryFilter)\n } else {\n const columnSingleValueQueryFilter: ColumnSingleValueQueryFilter = {\n columnName,\n operator: ColumnSingleValueFilterOperator.LIKE,\n values: [`%${searchText}%`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnSingleValueQueryFilter',\n }\n additionalFilters.push(columnSingleValueQueryFilter)\n }\n }\n } else {\n ;(\n additionalFilters[indexOfColumn] as\n | ColumnSingleValueQueryFilter\n | ColumnMultiValueFunctionQueryFilter\n ).values.push(`%${searchText}%`)\n }\n lastQueryRequestDeepClone.query.additionalFilters = additionalFilters\n executeQueryRequest(lastQueryRequestDeepClone)\n }\n\n public handleChange = (event: FormEvent<HTMLInputElement>) => {\n this.setState({\n searchText: event.currentTarget.value,\n })\n }\n\n public isSupportedColumn = (columnModel?: ColumnModel) => {\n switch (columnModel?.columnType) {\n case ColumnTypeEnum.FILEHANDLEID:\n case ColumnTypeEnum.DATE:\n case ColumnTypeEnum.DATE_LIST:\n case ColumnTypeEnum.USERID:\n // case ColumnTypeEnum.ENTITYID: //PORTALS-2995: users may want to search on Synapse ID\n return false\n default:\n return true\n }\n }\n\n public isSupportedColumnAndInProps = (columnModel?: ColumnModel) => {\n if (this.isSupportedColumn(columnModel)) {\n // return true if the searchable array contains this column name\n const { searchable } = this.props\n return searchable?.some(e => e === columnModel?.name)\n }\n return false\n }\n\n render() {\n const {\n searchable,\n lockedColumn,\n columnModels,\n queryVisualizationContext: { showSearchBar, getColumnDisplayName },\n } = this.props\n const { searchText, show, columnName } = this.state\n let searchColumns: string[] = []\n\n // searchable specifies the order of the columns to search\n if (searchable) {\n searchColumns = searchable\n .map(el => columnModels?.find(model => model.name === el))\n .filter(this.isSupportedColumnAndInProps)\n .map(el => el!.name)\n } else if (columnModels) {\n searchColumns = columnModels\n ?.filter(this.isSupportedColumn)\n .map(el => el.name)\n }\n\n // For study details page: if lockedColumn is defined, remove it from the radio dropdown\n if (searchColumns.length && lockedColumn?.columnName) {\n searchColumns = searchColumns.filter(\n el => el !== lockedColumn?.columnName,\n )\n }\n return (\n <div className={`QueryWrapperSearchInput`}>\n <Collapse in={showSearchBar}>\n <form\n className=\"QueryWrapperSearchInput__searchbar\"\n onSubmit={this.search}\n onClick={() => {\n this.setState({ show: true })\n }}\n ref={this.searchFormRef}\n >\n <span className=\"QueryWrapperSearchInput__searchbar__searchicon\">\n <IconSvg icon=\"search\" />\n </span>\n <input\n onChange={this.handleChange}\n onClick={() => {\n this.setState({\n show: true,\n })\n }}\n placeholder=\"Enter Search Terms\"\n value={searchText}\n type=\"text\"\n />\n {this.state.searchText.length > 0 && (\n <button\n className=\"QueryWrapperSearchInput__searchbar__clearbutton\"\n type=\"button\"\n onClick={() => {\n this.setState({\n searchText: '',\n })\n }}\n >\n <IconSvg icon=\"close\" />\n </button>\n )}\n </form>\n </Collapse>\n <div className=\"QueryWrapperSearchInput__dropdown_pos\">\n <CSSTransition\n nodeRef={this.radioFormRef}\n in={show}\n classNames=\"QueryWrapperSearchInput__animate_dropdown\"\n timeout={{ enter: 0, exit: 300 }}\n >\n <form\n ref={this.radioFormRef}\n className=\"QueryWrapperSearchInput__column-select QueryWrapperSearchInput__animate_height\"\n >\n <p className=\"deemphasized\">\n <i> Search In Field: </i>\n </p>\n {searchColumns.map((name, index) => {\n const displayName = getColumnDisplayName(name)\n const isSelected =\n (columnName === '' && index === 0) || columnName === name\n return (\n <div className=\"radio\" key={`search-field-${name}-${index}`}>\n <label>\n <span>\n <input\n id={name}\n type=\"radio\"\n value={name}\n checked={isSelected}\n onClick={() => {\n this.searchFormRef?.current\n ?.querySelector('input')\n ?.focus()\n this.setState({\n columnName: name,\n })\n }}\n />\n <span>{displayName}</span>\n </span>\n </label>\n </div>\n )\n })}\n </form>\n </CSSTransition>\n </div>\n </div>\n )\n }\n}\n\nexport default function Search(props: SearchV2Props) {\n const { data: queryMetadata } = useGetQueryMetadata()\n return <_Search {...props} columnModels={queryMetadata?.columnModels} />\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"SynapseTableRenderers.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseTable/SynapseTableRenderers.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,GAAG,EACJ,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,WAAW,EAEX,aAAa,EACd,MAAM,uBAAuB,CAAA;AA2D9B,eAAO,MAAM,kBAAkB,gEAQ7B,CAAA;AAuBF,eAAO,MAAM,uBAAuB,gEAQlC,CAAA;AAiBF,eAAO,MAAM,oBAAoB,gEAQ/B,CAAA;AAyEF,eAAO,MAAM,YAAY,gEAQvB,CAAA;AAEF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,2CAiEzC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,2CAkCnE"}
1
+ {"version":3,"file":"SynapseTableRenderers.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseTable/SynapseTableRenderers.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,GAAG,EACJ,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,WAAW,EAEX,aAAa,EACd,MAAM,uBAAuB,CAAA;AA2D9B,eAAO,MAAM,kBAAkB,gEAQ7B,CAAA;AAuBF,eAAO,MAAM,uBAAuB,gEAQlC,CAAA;AAiBF,eAAO,MAAM,oBAAoB,gEAQ/B,CAAA;AAyEF,eAAO,MAAM,YAAY,gEAQvB,CAAA;AAEF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,2CAiEzC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,2CAyCnE"}
@@ -133,7 +133,7 @@ function L(e) {
133
133
  function R(e) {
134
134
  let { cell: t, table: r } = e, { data: i } = n(), a = M(e), s = P(e), c = s === void 0 ? void 0 : parseInt(s), l = r.options.meta?.rowSet?.headers ?? [], u = l.find((e) => e.name === t.column.id), d = i?.columnModels ?? [], { columnLinks: f } = o();
135
135
  if (u) {
136
- let n = (f ?? []).find((e) => e.matchColumnName === u.name), r = u.columnType, i = t.column.getIsSorted() ? "SRC-boldText" : "";
136
+ let n = (f ?? []).find((e) => e.matchColumnName === u.name), r = d.find((e) => e.name === u.name)?.columnType ?? u.columnType, i = t.column.getIsSorted() ? "SRC-boldText" : "";
137
137
  return /* @__PURE__ */ v(p, {
138
138
  columnType: r,
139
139
  columnValue: t.getValue(),