synapse-react-client 4.0.20 → 4.0.22

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 (176) hide show
  1. package/dist/SWC.index.d.ts +1 -0
  2. package/dist/SWC.index.d.ts.map +1 -1
  3. package/dist/SWC.index.js +2 -1
  4. package/dist/SWC.index.js.map +1 -1
  5. package/dist/components/CardContainer/CardConfiguration.d.ts +2 -0
  6. package/dist/components/CardContainer/CardConfiguration.d.ts.map +1 -1
  7. package/dist/components/CardContainer/CardContainer.d.ts.map +1 -1
  8. package/dist/components/CardContainer/CardContainer.js +44 -50
  9. package/dist/components/CardContainer/CardContainer.js.map +1 -1
  10. package/dist/components/CardContainerLogic/CardContainerLogic.d.ts +14 -0
  11. package/dist/components/CardContainerLogic/CardContainerLogic.d.ts.map +1 -1
  12. package/dist/components/CardContainerLogic/CardContainerLogic.js +64 -40
  13. package/dist/components/CardContainerLogic/CardContainerLogic.js.map +1 -1
  14. package/dist/components/ChallengeSubmission/ChallengeSubmissionStepper.js +1 -1
  15. package/dist/components/ChallengeSubmission/ChallengeSubmissionStepper.js.map +1 -1
  16. package/dist/components/DataExplorer/DataExplorer.css +1 -1
  17. package/dist/components/DataExplorer/DataExplorer.module.js +16 -16
  18. package/dist/components/DataExplorer/DataExplorer.module.js.map +1 -1
  19. package/dist/components/DataExplorer/DataExplorer.module.scss +26 -7
  20. package/dist/components/DataGrid/DataGrid.d.ts +1 -0
  21. package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
  22. package/dist/components/DataGrid/DataGrid.js +72 -72
  23. package/dist/components/DataGrid/DataGrid.js.map +1 -1
  24. package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
  25. package/dist/components/DataGrid/SynapseGrid.js +209 -206
  26. package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
  27. package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.d.ts +6 -3
  28. package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.d.ts.map +1 -1
  29. package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.js +54 -46
  30. package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.js.map +1 -1
  31. package/dist/components/DataGrid/hooks/useColumnResizeHandles.d.ts.map +1 -1
  32. package/dist/components/DataGrid/hooks/useColumnResizeHandles.js +1 -1
  33. package/dist/components/DataGrid/hooks/useColumnResizeHandles.js.map +1 -1
  34. package/dist/components/DataGrid/useDataGridWebsocket.d.ts.map +1 -1
  35. package/dist/components/DataGrid/useDataGridWebsocket.js +68 -67
  36. package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
  37. package/dist/components/DataGrid/utils/columnFactory.d.ts +1 -0
  38. package/dist/components/DataGrid/utils/columnFactory.d.ts.map +1 -1
  39. package/dist/components/DataGrid/utils/columnFactory.js +5 -3
  40. package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
  41. package/dist/components/DataGrid/utils/modelColsToGrid.d.ts +1 -1
  42. package/dist/components/DataGrid/utils/modelColsToGrid.d.ts.map +1 -1
  43. package/dist/components/DataGrid/utils/modelColsToGrid.js +15 -14
  44. package/dist/components/DataGrid/utils/modelColsToGrid.js.map +1 -1
  45. package/dist/components/DataGrid/utils/normalizeWebsocketError.d.ts +7 -0
  46. package/dist/components/DataGrid/utils/normalizeWebsocketError.d.ts.map +1 -0
  47. package/dist/components/DataGrid/utils/normalizeWebsocketError.js +8 -0
  48. package/dist/components/DataGrid/utils/normalizeWebsocketError.js.map +1 -0
  49. package/dist/components/GenericCard/GenericCard.d.ts +2 -0
  50. package/dist/components/GenericCard/GenericCard.d.ts.map +1 -1
  51. package/dist/components/GenericCard/GenericCard.js +76 -64
  52. package/dist/components/GenericCard/GenericCard.js.map +1 -1
  53. package/dist/components/GenericCard/TableRowGenericCard.d.ts.map +1 -1
  54. package/dist/components/GenericCard/TableRowGenericCard.js +33 -25
  55. package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
  56. package/dist/components/Goals/Goals.d.ts +8 -0
  57. package/dist/components/Goals/Goals.d.ts.map +1 -1
  58. package/dist/components/Goals/Goals.js +54 -40
  59. package/dist/components/Goals/Goals.js.map +1 -1
  60. package/dist/components/Plot/SynapseSankeyPlot.css +1 -0
  61. package/dist/components/Plot/SynapseSankeyPlot.d.ts +44 -2
  62. package/dist/components/Plot/SynapseSankeyPlot.d.ts.map +1 -1
  63. package/dist/components/Plot/SynapseSankeyPlot.js +343 -38
  64. package/dist/components/Plot/SynapseSankeyPlot.js.map +1 -1
  65. package/dist/components/Plot/SynapseSankeyPlot.module.js +15 -0
  66. package/dist/components/Plot/SynapseSankeyPlot.module.js.map +1 -0
  67. package/dist/components/Plot/SynapseSankeyPlot.module.scss +63 -0
  68. package/dist/components/ProjectVisibilityChip/ProjectVisibilityChip.d.ts +9 -0
  69. package/dist/components/ProjectVisibilityChip/ProjectVisibilityChip.d.ts.map +1 -0
  70. package/dist/components/ProjectVisibilityChip/ProjectVisibilityChip.js +69 -0
  71. package/dist/components/ProjectVisibilityChip/ProjectVisibilityChip.js.map +1 -0
  72. package/dist/components/ProjectVisibilityChip/getProjectVisibilityFromACL.d.ts +13 -0
  73. package/dist/components/ProjectVisibilityChip/getProjectVisibilityFromACL.d.ts.map +1 -0
  74. package/dist/components/ProjectVisibilityChip/getProjectVisibilityFromACL.js +11 -0
  75. package/dist/components/ProjectVisibilityChip/getProjectVisibilityFromACL.js.map +1 -0
  76. package/dist/components/ProjectVisibilityChip/index.d.ts +5 -0
  77. package/dist/components/ProjectVisibilityChip/index.d.ts.map +1 -0
  78. package/dist/components/ProjectVisibilityChip/index.js +7 -0
  79. package/dist/components/ProjectVisibilityChip/index.js.map +1 -0
  80. package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.d.ts.map +1 -1
  81. package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js +1 -1
  82. package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js.map +1 -1
  83. package/dist/components/QueryWrapperPlotNav/RowSetView.d.ts.map +1 -1
  84. package/dist/components/QueryWrapperPlotNav/RowSetView.js +9 -12
  85. package/dist/components/QueryWrapperPlotNav/RowSetView.js.map +1 -1
  86. package/dist/components/RssFeedCards/RssFeedCards.d.ts +7 -15
  87. package/dist/components/RssFeedCards/RssFeedCards.d.ts.map +1 -1
  88. package/dist/components/RssFeedCards/RssFeedCards.js +114 -123
  89. package/dist/components/RssFeedCards/RssFeedCards.js.map +1 -1
  90. package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts +13 -12
  91. package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts.map +1 -1
  92. package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js +88 -77
  93. package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js.map +1 -1
  94. package/dist/components/SynapseTable/TopLevelControls/TopLevelControls.d.ts.map +1 -1
  95. package/dist/components/SynapseTable/TopLevelControls/TopLevelControls.js +63 -74
  96. package/dist/components/SynapseTable/TopLevelControls/TopLevelControls.js.map +1 -1
  97. package/dist/components/TableColumnSchemaEditor/ColumnModelForm.d.ts.map +1 -1
  98. package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js +72 -68
  99. package/dist/components/TableColumnSchemaEditor/ColumnModelForm.js.map +1 -1
  100. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts +27 -1
  101. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.d.ts.map +1 -1
  102. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.js +47 -36
  103. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaEditorUtils.js.map +1 -1
  104. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js +1 -1
  105. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
  106. package/dist/components/TableColumnSchemaEditor/TableColumnSchemaFormReducer.d.ts +12 -12
  107. package/dist/components/TableColumnSchemaEditor/Validators/BooleanSchema.d.ts +4 -1
  108. package/dist/components/TableColumnSchemaEditor/Validators/BooleanSchema.d.ts.map +1 -1
  109. package/dist/components/TableColumnSchemaEditor/Validators/ColumnModelValidator.d.ts +167 -517
  110. package/dist/components/TableColumnSchemaEditor/Validators/ColumnModelValidator.d.ts.map +1 -1
  111. package/dist/components/TableColumnSchemaEditor/Validators/ColumnModelValidator.js +65 -65
  112. package/dist/components/TableColumnSchemaEditor/Validators/ColumnModelValidator.js.map +1 -1
  113. package/dist/components/TableColumnSchemaEditor/Validators/DatetimeSchema.d.ts +1 -1
  114. package/dist/components/TableColumnSchemaEditor/Validators/DatetimeSchema.d.ts.map +1 -1
  115. package/dist/components/TableColumnSchemaEditor/Validators/DoubleSchema.d.ts +1 -1
  116. package/dist/components/TableColumnSchemaEditor/Validators/DoubleSchema.d.ts.map +1 -1
  117. package/dist/components/TableColumnSchemaEditor/Validators/DoubleSchema.js +6 -13
  118. package/dist/components/TableColumnSchemaEditor/Validators/DoubleSchema.js.map +1 -1
  119. package/dist/components/TableColumnSchemaEditor/Validators/EntityIdSchema.d.ts +1 -1
  120. package/dist/components/TableColumnSchemaEditor/Validators/EntityIdSchema.d.ts.map +1 -1
  121. package/dist/components/TableColumnSchemaEditor/Validators/IntegerSchema.d.ts +1 -1
  122. package/dist/components/TableColumnSchemaEditor/Validators/IntegerSchema.d.ts.map +1 -1
  123. package/dist/components/TableColumnSchemaEditor/Validators/IntegerSchema.js +2 -2
  124. package/dist/components/TableColumnSchemaEditor/Validators/IntegerSchema.js.map +1 -1
  125. package/dist/components/TableColumnSchemaEditor/Validators/OptionalStringSchema.d.ts +1 -1
  126. package/dist/components/TableColumnSchemaEditor/Validators/OptionalStringSchema.d.ts.map +1 -1
  127. package/dist/components/TableColumnSchemaEditor/Validators/getZodSchemaForColumnType.d.ts +2 -2
  128. package/dist/components/TableColumnSchemaEditor/Validators/getZodSchemaForColumnType.d.ts.map +1 -1
  129. package/dist/components/TableColumnSchemaEditor/Validators/getZodSchemaForColumnType.js +15 -16
  130. package/dist/components/TableColumnSchemaEditor/Validators/getZodSchemaForColumnType.js.map +1 -1
  131. package/dist/components/UserCardList/UserCardList.d.ts +2 -20
  132. package/dist/components/UserCardList/UserCardList.d.ts.map +1 -1
  133. package/dist/components/UserCardList/UserCardList.js +49 -72
  134. package/dist/components/UserCardList/UserCardList.js.map +1 -1
  135. package/dist/components/UserCardList/UserCardListRotate.d.ts +13 -0
  136. package/dist/components/UserCardList/UserCardListRotate.d.ts.map +1 -1
  137. package/dist/components/UserCardList/UserCardListRotate.js +82 -57
  138. package/dist/components/UserCardList/UserCardListRotate.js.map +1 -1
  139. package/dist/mocks/mockSearchQueryData.js +2 -2
  140. package/dist/mocks/mockSearchQueryData.js.map +1 -1
  141. package/dist/mocks/msw/handlers/searchQueryHandlers.d.ts +1 -1
  142. package/dist/mocks/msw/handlers/searchQueryHandlers.d.ts.map +1 -1
  143. package/dist/mocks/msw/handlers/searchQueryHandlers.js +6 -3
  144. package/dist/mocks/msw/handlers/searchQueryHandlers.js.map +1 -1
  145. package/dist/mocks/query/mockUserCardTableQueryResultBundle.d.ts +13 -0
  146. package/dist/mocks/query/mockUserCardTableQueryResultBundle.d.ts.map +1 -1
  147. package/dist/mocks/query/mockUserCardTableQueryResultBundle.js +27 -0
  148. package/dist/mocks/query/mockUserCardTableQueryResultBundle.js.map +1 -1
  149. package/dist/style/abstracts/_cssVariables.scss +1 -0
  150. package/dist/style/components/_cards.scss +10 -0
  151. package/dist/style/components/_data-grid-extra.css +1 -1
  152. package/dist/style/components/_data-grid-extra.scss +7 -1
  153. package/dist/style/main.css +1 -1
  154. package/dist/synapse-client/SynapseClient.d.ts.map +1 -1
  155. package/dist/synapse-client/SynapseClient.js +497 -495
  156. package/dist/synapse-client/SynapseClient.js.map +1 -1
  157. package/dist/synapse-queries/KeyFactory.d.ts +1 -0
  158. package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
  159. package/dist/synapse-queries/KeyFactory.js +3 -0
  160. package/dist/synapse-queries/KeyFactory.js.map +1 -1
  161. package/dist/synapse-queries/index.js +46 -44
  162. package/dist/synapse-queries/user/index.js +3 -3
  163. package/dist/synapse-queries/user/useUserBundle.d.ts +12 -0
  164. package/dist/synapse-queries/user/useUserBundle.d.ts.map +1 -1
  165. package/dist/synapse-queries/user/useUserBundle.js +50 -36
  166. package/dist/synapse-queries/user/useUserBundle.js.map +1 -1
  167. package/dist/tsconfig.build.tsbuildinfo +1 -1
  168. package/dist/utils/AppUtils/session/SessionInitializedGuard.d.ts +10 -5
  169. package/dist/utils/AppUtils/session/SessionInitializedGuard.d.ts.map +1 -1
  170. package/dist/utils/AppUtils/session/SessionInitializedGuard.js +13 -9
  171. package/dist/utils/AppUtils/session/SessionInitializedGuard.js.map +1 -1
  172. package/dist/utils/functions/SqlFunctions.d.ts +1 -1
  173. package/dist/utils/functions/SqlFunctions.d.ts.map +1 -1
  174. package/dist/utils/functions/SqlFunctions.js +1 -1
  175. package/dist/utils/functions/SqlFunctions.js.map +1 -1
  176. package/package.json +7 -5
@@ -1 +1 @@
1
- {"version":3,"file":"SearchQueryUseQueryOptions.js","names":[],"sources":["../../../src/components/SearchQueryWrapper/SearchQueryUseQueryOptions.ts"],"sourcesContent":["import * as SynapseClient from '@/synapse-client/SynapseClient'\nimport { tableQueryUseQueryDefaults } from '@/synapse-queries'\nimport { useGetEntityBundle } from '@/synapse-queries/entity/useEntityBundle'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport {\n AsynchronousJobStatus,\n ColumnModel,\n FACET_COLUMN_RANGE_REQUEST_CONCRETE_TYPE_VALUE,\n FacetColumnRangeRequest,\n FacetColumnResultRange,\n FACET_COLUMN_VALUES_REQUEST_CONCRETE_TYPE_VALUE,\n FacetColumnValuesRequest,\n QueryBundleRequest,\n QueryResultBundle,\n RowSet,\n SortItem,\n TEXT_MATCHES_QUERY_FILTER_CONCRETE_TYPE_VALUE,\n TextMatchesQueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport type {\n FacetRequest,\n KeyValues,\n SearchIndexQuery,\n SearchKeyRange,\n SearchQueryResults,\n SearchSearchQuery,\n SearchSortField,\n SynapseClientError,\n} from '@sage-bionetworks/synapse-client'\nimport {\n FacetRequestSortDirectionEnum as FacetRequestSortDirectionEnumValues,\n FacetRequestSortFieldEnum as FacetRequestSortFieldEnumValues,\n} from '@sage-bionetworks/synapse-client'\nimport {\n InfiniteData,\n QueryKey,\n UseInfiniteQueryOptions,\n UseSuspenseQueryOptions,\n} from '@tanstack/react-query'\nimport { omit } from 'lodash-es'\nimport dayjs from 'dayjs'\nimport { useCallback, useMemo } from 'react'\nimport { KeyFactory } from '@/synapse-queries/KeyFactory'\n\n/**\n * TanStack Query options for the SearchQueryServicesApi, mirroring TableQueryUseQueryOptions\n * but parameterised over SearchIndexQuery rather than QueryBundleRequest. This eliminates\n * `as unknown as` casts inside the implementation. A single cast to TableQueryUseQueryOptions\n * is still required at the boundary where SearchQueryWrapper assigns these into QueryContextType.\n */\nexport type SearchTableQueryUseQueryOptions = {\n rowDataQueryOptions: UseSuspenseQueryOptions<\n AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n SynapseClientError,\n RowSet | undefined\n >\n rowDataInfiniteQueryOptions: UseInfiniteQueryOptions<\n AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n SynapseClientError,\n InfiniteData<AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>>,\n QueryKey,\n string | number | undefined\n >\n queryMetadataQueryOptions: UseSuspenseQueryOptions<\n AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n SynapseClientError,\n Omit<QueryResultBundle, 'queryResult'>\n >\n}\n\n/**\n * Converts a QueryBundleRequest (used internally for state management) into a SearchIndexQuery\n * that can be sent to the SearchQueryServicesApi.\n *\n * Mapping:\n * - columnModels (facetType defined) → facetRequests (columns to aggregate as facets, with optional sort config)\n * - query.selectedFacets (enumeration) → termsFilters (IN-clause filters)\n * - query.selectedFacets (range) → rangeFilters (range filters)\n * - query.sort → sort (SortItem { column, direction } → SearchSortField { columnName, direction })\n * - query.limit → limit\n * - query.offset → offset\n * - partMask → dropped (SearchIndexQuery has no bitmask concept)\n */\nexport function toSearchIndexQuery(\n queryBundleRequest: QueryBundleRequest,\n searchIndexId: string,\n columnModels?: ColumnModel[],\n): SearchIndexQuery {\n // Build facetRequests from ColumnModels that have a facetType of 'enumeration'.\n // Range columns are excluded: the Search API's FacetRequest only supports terms aggregations\n // and cannot produce the min/max stats needed for FacetColumnResultRange.\n const facetRequests: FacetRequest[] | undefined = columnModels\n ?.filter(cm => cm.facetType === 'enumeration')\n .map(cm => {\n const facetReq: FacetRequest = { columnName: cm.name, maxValueCount: 100 }\n if (cm.facetSortConfig) {\n // Map FacetColumnSortProperty ('FREQUENCY'|'VALUE') → FacetRequestSortFieldEnum ('COUNT'|'KEY')\n if (cm.facetSortConfig.property != null) {\n facetReq.sortField =\n cm.facetSortConfig.property === 'VALUE'\n ? FacetRequestSortFieldEnumValues.KEY\n : FacetRequestSortFieldEnumValues.COUNT\n }\n if (cm.facetSortConfig.direction != null) {\n facetReq.sortDirection =\n cm.facetSortConfig.direction === 'ASC'\n ? FacetRequestSortDirectionEnumValues.ASC\n : FacetRequestSortDirectionEnumValues.DESC\n }\n }\n return facetReq\n })\n\n // Build termsFilters from enumeration selectedFacets\n const termsFilters: KeyValues[] | undefined =\n queryBundleRequest.query.selectedFacets\n ?.filter(\n (f): f is FacetColumnValuesRequest =>\n f.concreteType === FACET_COLUMN_VALUES_REQUEST_CONCRETE_TYPE_VALUE,\n )\n .map(f => ({ key: f.columnName, values: f.facetValues }))\n\n // Build rangeFilters from range selectedFacets.\n // DATE columns: the Range UI component emits formatted dates (\"YYYY-MM-DD\") but the\n // Search API (OpenSearch) expects unix millisecond timestamps. Convert here.\n const rangeFilters: SearchKeyRange[] | undefined =\n queryBundleRequest.query.selectedFacets\n ?.filter(\n (f): f is FacetColumnRangeRequest =>\n f.concreteType === FACET_COLUMN_RANGE_REQUEST_CONCRETE_TYPE_VALUE,\n )\n .map(f => {\n const columnType = columnModels?.find(\n cm => cm.name === f.columnName,\n )?.columnType\n const toApiValue = (v: string | undefined): string | undefined => {\n if (!v || columnType !== 'DATE') return v\n // Convert \"YYYY-MM-DD\" → unix ms; leave already-numeric values untouched\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(v)) {\n return String(dayjs(v).valueOf())\n }\n return v\n }\n return {\n key: f.columnName,\n min: toApiValue(f.min),\n max: toApiValue(f.max),\n }\n })\n\n // Extract queryText by concatenating all TextMatchesQueryFilter searchExpression values\n const textMatchesExpressions = queryBundleRequest.query.additionalFilters\n ?.filter(\n (f): f is TextMatchesQueryFilter =>\n f.concreteType === TEXT_MATCHES_QUERY_FILTER_CONCRETE_TYPE_VALUE,\n )\n .map(f => f.searchExpression)\n .filter((expr): expr is string => expr != null && expr.length > 0)\n const queryText =\n textMatchesExpressions && textMatchesExpressions.length > 0\n ? textMatchesExpressions.join(' ')\n : undefined\n\n // Map SortItem[] (column + direction) → SearchSortField[] (columnName + direction),\n // filtering out entries with no direction (which mean \"remove sort\").\n const sort: SearchSortField[] | undefined = queryBundleRequest.query.sort\n ?.filter(\n (s): s is SortItem & { direction: 'ASC' | 'DESC' } =>\n s.direction === 'ASC' || s.direction === 'DESC',\n )\n .map(s => ({ columnName: s.column, direction: s.direction }))\n\n const searchQuery: SearchSearchQuery = {\n facetRequests: facetRequests?.length ? facetRequests : undefined,\n termsFilters: termsFilters?.length ? termsFilters : undefined,\n rangeFilters: rangeFilters?.length ? rangeFilters : undefined,\n queryText,\n queryType: 'MULTI_MATCH',\n fuzziness: 'AUTO',\n sort: sort?.length ? sort : undefined,\n limit: queryBundleRequest.query.limit,\n offset: queryBundleRequest.query.offset,\n }\n\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.search.table.SearchIndexQuery' as const,\n searchIndexId,\n searchQuery,\n }\n}\n\n/**\n * Converts a SearchQueryResults (the actual API response) into a QueryResultBundle\n * so that existing subcomponents (FacetFilterControls, RowSetView, etc.) work unchanged.\n *\n * Mapping:\n * - totalHits → queryCount\n * - hits → queryResult.queryResults (rows derived from hit.rowId/rowVersion/fields)\n * - facets → facets (same FacetColumnResult type)\n */\nexport function searchQueryResultsToQueryResultBundle(\n results: SearchQueryResults | undefined,\n query: SearchIndexQuery,\n columnModels?: ColumnModel[],\n): QueryResultBundle {\n if (!results) {\n return {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryResultBundle',\n }\n }\n\n // Derive column names from the server-returned selectColumns. Both the row data\n // query and the metadata query request SELECT_COLUMNS, so this is always present.\n const fieldNames: string[] =\n results.selectColumns\n ?.map(col => col.name)\n .filter((n): n is string => !!n) ?? []\n\n const headers = fieldNames.map(name => ({\n name,\n columnType:\n columnModels?.find(cm => cm.name === name)?.columnType ??\n ('STRING' as const),\n }))\n\n const rows = (results.hits ?? []).map(hit => ({\n rowId: hit.rowId,\n versionNumber: hit.rowVersion,\n values: fieldNames.map(name => {\n return hit.fields?.find(f => f.name === name)?.value ?? null\n }),\n }))\n\n const queryResult =\n headers.length > 0 || rows.length > 0\n ? {\n concreteType:\n 'org.sagebionetworks.repo.model.table.QueryResult' as const,\n queryResults: {\n concreteType:\n 'org.sagebionetworks.repo.model.table.RowSet' as const,\n tableId: query.searchIndexId ?? '',\n etag: '',\n headers,\n rows,\n },\n }\n : undefined\n\n const rawFacets = results.facets as QueryResultBundle['facets']\n\n // Synthesize FacetColumnResultRange for range-type DATE/DOUBLE/INTEGER columns. The Search API's\n // FacetRequest only produces terms aggregations and cannot return min/max stats, so these\n // entries will never appear in results.facets. columnMin/columnMax are empty strings\n // (unavailable from the server); selectedMin/selectedMax are derived from the query's\n // rangeFilters so any applied range filter is still reflected in the UI.\n // Note: for INTEGER columns the RangeSlider requires real bounds, so the UI falls back to a\n // plain Range number input when columnMin/columnMax are absent.\n const syntheticRangeFacets: FacetColumnResultRange[] = (columnModels ?? [])\n .filter(\n cm =>\n cm.facetType === 'range' &&\n (cm.columnType === 'DATE' ||\n cm.columnType === 'DOUBLE' ||\n cm.columnType === 'INTEGER') &&\n !(rawFacets ?? []).some(f => f.columnName === cm.name),\n )\n .map(cm => {\n const rangeFilter = query.searchQuery?.rangeFilters?.find(\n rf => rf.key === cm.name,\n )\n // rangeFilters carry unix ms for DATE columns (converted in toSearchIndexQuery).\n // Convert back to \"YYYY-MM-DD\" so the Range UI component can display them.\n const toDisplayValue = (v: string | undefined): string | undefined => {\n if (!v || cm.columnType !== 'DATE') return v\n if (/^\\d+$/.test(v)) {\n return dayjs(parseInt(v)).format('YYYY-MM-DD')\n }\n return v\n }\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.table.FacetColumnResultRange' as const,\n facetType: 'range' as const,\n columnName: cm.name,\n columnMin: '',\n columnMax: '',\n selectedMin: toDisplayValue(rangeFilter?.min),\n selectedMax: toDisplayValue(rangeFilter?.max),\n }\n })\n\n const allFacets: NonNullable<QueryResultBundle['facets']> = [\n ...(rawFacets ?? []),\n ...syntheticRangeFacets,\n ]\n\n // Reorder all facets to match the columnModels order so downstream components\n // (e.g. FacetFilterControls) render facets in the expected column order.\n const orderedFacets: QueryResultBundle['facets'] = columnModels\n ? [\n ...allFacets\n .filter(f => columnModels.some(cm => cm.name === f.columnName))\n .sort(\n (a, b) =>\n columnModels.findIndex(cm => cm.name === a.columnName) -\n columnModels.findIndex(cm => cm.name === b.columnName),\n ),\n ...allFacets.filter(\n f => !columnModels.some(cm => cm.name === f.columnName),\n ),\n ]\n : allFacets\n\n return {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryResultBundle',\n queryCount: results.totalHits,\n selectColumns: headers,\n queryResult,\n facets: orderedFacets,\n }\n}\n\nexport function getSearchQueryUseQueryOptions(\n queryBundleRequest: QueryBundleRequest,\n keyFactory: KeyFactory,\n accessToken: string | undefined,\n searchIndexId: string,\n columnModels?: ColumnModel[],\n): SearchTableQueryUseQueryOptions {\n const baseQuery: SearchIndexQuery = toSearchIndexQuery(\n queryBundleRequest,\n searchIndexId,\n columnModels,\n )\n const rowDataQuery: SearchIndexQuery = {\n ...baseQuery,\n searchQuery: {\n ...baseQuery.searchQuery,\n // Omit facetRequests from the row data query: facet aggregations are only needed\n // in the metadata query (which requests FACETS). Removing facetRequests here keeps\n // the row data query key stable while column models are loading, preventing an\n // unnecessary re-fetch (and a brief loading flash) when column models first arrive.\n facetRequests: undefined,\n },\n // Request SELECT_COLUMNS so headers are available for row rendering.\n // HITS is returned by default even when responseParts is specified.\n responseParts: new Set(['HITS', 'SELECT_COLUMNS'] as const),\n }\n const metadataQuery: SearchIndexQuery = {\n ...baseQuery,\n // Request all opt-in parts needed for the metadata response:\n // TOTAL_HITS → queryCount (drives tab count / spinner resolution)\n // SELECT_COLUMNS → column headers for the table\n // FACETS → facet aggregations for FacetFilterControls / plots\n responseParts: new Set(['TOTAL_HITS', 'SELECT_COLUMNS', 'FACETS'] as const),\n }\n\n // Convert responseParts Set → sorted array for query key building.\n // JSON.stringify(new Set([...])) === '{}', so two queries whose only difference is\n // their responseParts would hash to the same key and share a cache entry.\n // Using a sorted array gives each query a distinct, stable key.\n const toKeyShape = (query: SearchIndexQuery) => ({\n ...query,\n responseParts: query.responseParts\n ? [...query.responseParts].sort()\n : undefined,\n })\n\n // Fetches from the SearchQueryServicesApi and converts the SearchQueryResults responseBody\n // into QueryResultBundle shape. This allows all downstream shared components\n // (UseRowSet, QueryVisualizationWrapper, etc.) to access data.responseBody.*\n // using the same patterns as regular table queries (queryResult.queryResults, selectColumns, etc.).\n const fetchAndConvert = async (query: SearchIndexQuery) => {\n const asyncStatus = await SynapseClient.getSearchQueryAsyncJobResults(\n query,\n accessToken,\n )\n return {\n ...asyncStatus,\n responseBody: searchQueryResultsToQueryResultBundle(\n asyncStatus.responseBody,\n query,\n columnModels,\n ),\n }\n }\n\n // `as unknown as` is necessary because SearchIndexQuery.responseParts is a Set but\n // toKeyShape converts it to a sorted string[] for stable cache key serialisation.\n const rowDataQueryOptions: SearchTableQueryUseQueryOptions['rowDataQueryOptions'] =\n {\n ...tableQueryUseQueryDefaults,\n queryKey: keyFactory.getSearchQueryResultWithAsyncStatusQueryKey(\n toKeyShape(rowDataQuery) as unknown as SearchIndexQuery,\n false,\n ),\n queryFn: () => fetchAndConvert(rowDataQuery),\n select: (\n data: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n ): RowSet | undefined => data.responseBody?.queryResult?.queryResults,\n }\n\n const rowDataInfiniteQueryOptions: SearchTableQueryUseQueryOptions['rowDataInfiniteQueryOptions'] =\n {\n ...tableQueryUseQueryDefaults,\n queryKey: keyFactory.getSearchQueryResultWithAsyncStatusQueryKey(\n toKeyShape(rowDataQuery) as unknown as SearchIndexQuery,\n true,\n ),\n initialPageParam: 0 as number | string | undefined,\n getNextPageParam: (\n lastPage: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n allPages: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>[],\n ): number | string | undefined => {\n const totalRows = lastPage.responseBody?.queryCount\n const fetchedRows = allPages.reduce(\n (acc, page) =>\n acc +\n (page.responseBody?.queryResult?.queryResults.rows?.length ?? 0),\n 0,\n )\n if (totalRows != null && fetchedRows >= totalRows) {\n return undefined\n }\n return fetchedRows\n },\n queryFn: (context: { pageParam?: number | string }) => {\n const offset =\n typeof context.pageParam === 'string'\n ? parseInt(context.pageParam)\n : (context.pageParam ?? 0)\n const requestForPage: SearchIndexQuery = {\n ...rowDataQuery,\n searchQuery: {\n ...rowDataQuery.searchQuery,\n offset,\n },\n }\n return fetchAndConvert(requestForPage)\n },\n select: (\n data: InfiniteData<\n AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>\n >,\n ) => data,\n }\n\n const queryMetadataQueryOptions: SearchTableQueryUseQueryOptions['queryMetadataQueryOptions'] =\n {\n ...tableQueryUseQueryDefaults,\n queryKey: keyFactory.getSearchQueryResultWithAsyncStatusQueryKey(\n toKeyShape(metadataQuery) as unknown as SearchIndexQuery,\n false,\n ),\n queryFn: () => fetchAndConvert(metadataQuery),\n select: (\n data: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n ): Omit<QueryResultBundle, 'queryResult'> => {\n const result = omit(data.responseBody ?? {}, 'queryResult') as Omit<\n QueryResultBundle,\n 'queryResult'\n >\n return columnModels ? { ...result, columnModels } : result\n },\n }\n\n return {\n rowDataQueryOptions,\n rowDataInfiniteQueryOptions,\n queryMetadataQueryOptions,\n }\n}\n\n/**\n * Returns a stable callback that fetches autocomplete suggestions for a search input\n * using the synchronous `POST /search/autocomplete` endpoint.\n *\n * The query is built from the current `searchIndexId` and `autocompleteFieldName`:\n * - `searchQuery.queryText` is set to the user-entered search text\n * - `searchQuery.queryFields` is set to `[autocompleteFieldName]` so the server\n * only returns values for that single field\n *\n * When `autocompleteFieldName` is undefined, the returned callback immediately returns `[]`.\n */\nexport function useGetSuggestionsForSearchIndex(\n searchIndexId: string,\n autocompleteFieldName: string | undefined,\n): (searchText: string) => Promise<string[]> {\n const { synapseClient } = useSynapseContext()\n\n return useCallback(\n async (searchText: string): Promise<string[]> => {\n if (!autocompleteFieldName) return []\n const trimmed = searchText.trim()\n if (!trimmed) return []\n const results =\n await synapseClient.searchManagementServicesClient.postRepoV1SearchAutocomplete(\n {\n searchIndexQuery: {\n concreteType:\n 'org.sagebionetworks.repo.model.search.table.SearchIndexQuery' as const,\n searchIndexId,\n searchQuery: {\n queryText: trimmed,\n queryFields: [autocompleteFieldName],\n returnFields: [autocompleteFieldName],\n },\n },\n },\n )\n const suggestions: string[] = []\n for (const hit of results.hits ?? []) {\n for (const field of hit.fields ?? []) {\n if (field.value) {\n suggestions.push(field.value)\n }\n }\n }\n return suggestions\n },\n [synapseClient, searchIndexId, autocompleteFieldName],\n )\n}\n\n/**\n * Returns TanStack Query options that call the SearchQueryServicesApi (instead of the\n * standard Table Query API) but return data in the same QueryResultBundle format, allowing\n * all existing subcomponents (FacetFilterControls, RowSetView, etc.) to work unchanged.\n */\nexport function useSearchQueryUseQueryOptions(\n queryBundleRequest: QueryBundleRequest,\n searchIndexId: string,\n synapseId?: string,\n): SearchTableQueryUseQueryOptions {\n const { keyFactory, accessToken } = useSynapseContext()\n\n const { data: entityBundle } = useGetEntityBundle(synapseId, undefined, {\n includeTableBundle: true,\n })\n const columnModels = entityBundle?.tableBundle?.columnModels\n\n return useMemo(\n () =>\n getSearchQueryUseQueryOptions(\n queryBundleRequest,\n keyFactory,\n accessToken,\n searchIndexId,\n columnModels,\n ),\n [keyFactory, accessToken, queryBundleRequest, searchIndexId, columnModels],\n )\n}\n"],"mappings":";;;;;;;;;;;AAmFA,SAAgB,EACd,GACA,GACA,GACkB;CAIlB,IAAM,IAA4C,GAC9C,QAAO,MAAM,EAAG,cAAc,aAAa,EAC5C,KAAI,MAAM;EACT,IAAM,IAAyB;GAAE,YAAY,EAAG;GAAM,eAAe;EAAI;EAgBzE,OAfI,EAAG,oBAED,EAAG,gBAAgB,YAAY,SACjC,EAAS,YACP,EAAG,gBAAgB,aAAa,UAC5B,EAAgC,MAChC,EAAgC,QAEpC,EAAG,gBAAgB,aAAa,SAClC,EAAS,gBACP,EAAG,gBAAgB,cAAc,QAC7B,EAAoC,MACpC,EAAoC,QAGvC;CACT,CAAC,GAGG,IACJ,EAAmB,MAAM,gBACrB,QACC,MACC,EAAE,iBAAiB,CACvB,EACC,KAAI,OAAM;EAAE,KAAK,EAAE;EAAY,QAAQ,EAAE;CAAY,EAAE,GAKtD,IACJ,EAAmB,MAAM,gBACrB,QACC,MACC,EAAE,iBAAiB,CACvB,EACC,KAAI,MAAK;EACR,IAAM,IAAa,GAAc,MAC/B,MAAM,EAAG,SAAS,EAAE,UACtB,GAAG,YACG,KAAc,MACd,CAAC,KAAK,MAAe,SAAe,IAEpC,sBAAsB,KAAK,CAAC,IACvB,OAAO,EAAM,CAAC,EAAE,QAAQ,CAAC,IAE3B;EAET,OAAO;GACL,KAAK,EAAE;GACP,KAAK,EAAW,EAAE,GAAG;GACrB,KAAK,EAAW,EAAE,GAAG;EACvB;CACF,CAAC,GAGC,IAAyB,EAAmB,MAAM,mBACpD,QACC,MACC,EAAE,iBAAiB,CACvB,EACC,KAAI,MAAK,EAAE,gBAAgB,EAC3B,QAAQ,MAAyB,KAAQ,QAAQ,EAAK,SAAS,CAAC,GAC7D,IACJ,KAA0B,EAAuB,SAAS,IACtD,EAAuB,KAAK,GAAG,IAC/B,KAAA,GAIA,IAAsC,EAAmB,MAAM,MACjE,QACC,MACC,EAAE,cAAc,SAAS,EAAE,cAAc,MAC7C,EACC,KAAI,OAAM;EAAE,YAAY,EAAE;EAAQ,WAAW,EAAE;CAAU,EAAE;CAc9D,OAAO;EACL,cACE;EACF;EACA,aAAA;GAfA,eAAe,GAAe,SAAS,IAAgB,KAAA;GACvD,cAAc,GAAc,SAAS,IAAe,KAAA;GACpD,cAAc,GAAc,SAAS,IAAe,KAAA;GACpD;GACA,WAAW;GACX,WAAW;GACX,MAAM,GAAM,SAAS,IAAO,KAAA;GAC5B,OAAO,EAAmB,MAAM;GAChC,QAAQ,EAAmB,MAAM;EAOjC;CACF;AACF;AAWA,SAAgB,EACd,GACA,GACA,GACmB;CACnB,IAAI,CAAC,GACH,OAAO,EACL,cAAc,yDAChB;CAKF,IAAM,IACJ,EAAQ,eACJ,KAAI,MAAO,EAAI,IAAI,EACpB,QAAQ,MAAmB,CAAC,CAAC,CAAC,KAAK,CAAC,GAEnC,IAAU,EAAW,KAAI,OAAS;EACtC;EACA,YACE,GAAc,MAAK,MAAM,EAAG,SAAS,CAAI,GAAG,cAC3C;CACL,EAAE,GAEI,KAAQ,EAAQ,QAAQ,CAAC,GAAG,KAAI,OAAQ;EAC5C,OAAO,EAAI;EACX,eAAe,EAAI;EACnB,QAAQ,EAAW,KAAI,MACd,EAAI,QAAQ,MAAK,MAAK,EAAE,SAAS,CAAI,GAAG,SAAS,IACzD;CACH,EAAE,GAEI,IACJ,EAAQ,SAAS,KAAK,EAAK,SAAS,IAChC;EACE,cACE;EACF,cAAc;GACZ,cACE;GACF,SAAS,EAAM,iBAAiB;GAChC,MAAM;GACN;GACA;EACF;CACF,IACA,KAAA,GAEA,IAAY,EAAQ,QASpB,KAAkD,KAAgB,CAAC,GACtE,QACC,MACE,EAAG,cAAc,YAChB,EAAG,eAAe,UACjB,EAAG,eAAe,YAClB,EAAG,eAAe,cACpB,EAAE,KAAa,CAAC,GAAG,MAAK,MAAK,EAAE,eAAe,EAAG,IAAI,CACzD,EACC,KAAI,MAAM;EACT,IAAM,IAAc,EAAM,aAAa,cAAc,MACnD,MAAM,EAAG,QAAQ,EAAG,IACtB,GAGM,KAAkB,MAClB,CAAC,KAAK,EAAG,eAAe,SAAe,IACvC,QAAQ,KAAK,CAAC,IACT,EAAM,SAAS,CAAC,CAAC,EAAE,OAAO,YAAY,IAExC;EAET,OAAO;GACL,cACE;GACF,WAAW;GACX,YAAY,EAAG;GACf,WAAW;GACX,WAAW;GACX,aAAa,EAAe,GAAa,GAAG;GAC5C,aAAa,EAAe,GAAa,GAAG;EAC9C;CACF,CAAC,GAEG,IAAsD,CAC1D,GAAI,KAAa,CAAC,GAClB,GAAG,CACL,GAIM,IAA6C,IAC/C,CACE,GAAG,EACA,QAAO,MAAK,EAAa,MAAK,MAAM,EAAG,SAAS,EAAE,UAAU,CAAC,EAC7D,MACE,GAAG,MACF,EAAa,WAAU,MAAM,EAAG,SAAS,EAAE,UAAU,IACrD,EAAa,WAAU,MAAM,EAAG,SAAS,EAAE,UAAU,CACzD,GACF,GAAG,EAAU,QACX,MAAK,CAAC,EAAa,MAAK,MAAM,EAAG,SAAS,EAAE,UAAU,CACxD,CACF,IACA;CAEJ,OAAO;EACL,cAAc;EACd,YAAY,EAAQ;EACpB,eAAe;EACf;EACA,QAAQ;CACV;AACF;AAEA,SAAgB,EACd,GACA,GACA,GACA,GACA,GACiC;CACjC,IAAM,IAA8B,EAClC,GACA,GACA,CACF,GACM,IAAiC;EACrC,GAAG;EACH,aAAa;GACX,GAAG,EAAU;GAKb,eAAe,KAAA;EACjB;EAGA,eAAe,IAAI,IAAI,CAAC,QAAQ,gBAAgB,CAAU;CAC5D,GACM,IAAkC;EACtC,GAAG;EAKH,eAAe,IAAI,IAAI;GAAC;GAAc;GAAkB;EAAQ,CAAU;CAC5E,GAMM,KAAc,OAA6B;EAC/C,GAAG;EACH,eAAe,EAAM,gBACjB,CAAC,GAAG,EAAM,aAAa,EAAE,KAAK,IAC9B,KAAA;CACN,IAMM,IAAkB,OAAO,MAA4B;EACzD,IAAM,IAAc,MAAM,EACxB,GACA,CACF;EACA,OAAO;GACL,GAAG;GACH,cAAc,EACZ,EAAY,cACZ,GACA,CACF;EACF;CACF;CAiFA,OAAO;EACL,qBAAA;GA5EE,GAAG;GACH,UAAU,EAAW,4CACnB,EAAW,CAAY,GACvB,EACF;GACA,eAAe,EAAgB,CAAY;GAC3C,SACE,MACuB,EAAK,cAAc,aAAa;EAoE3D;EACA,6BAAA;GAhEE,GAAG;GACH,UAAU,EAAW,4CACnB,EAAW,CAAY,GACvB,EACF;GACA,kBAAkB;GAClB,mBACE,GACA,MACgC;IAChC,IAAM,IAAY,EAAS,cAAc,YACnC,IAAc,EAAS,QAC1B,GAAK,MACJ,KACC,EAAK,cAAc,aAAa,aAAa,MAAM,UAAU,IAChE,CACF;IACI,WAAa,QAAQ,KAAe,IAGxC,OAAO;GACT;GACA,UAAU,MAA6C;IACrD,IAAM,IACJ,OAAO,EAAQ,aAAc,WACzB,SAAS,EAAQ,SAAS,IACzB,EAAQ,aAAa;IAQ5B,OAAO,EAAgB;KANrB,GAAG;KACH,aAAa;MACX,GAAG,EAAa;MAChB;KACF;IAEqB,CAAc;GACvC;GACA,SACE,MAGG;EAwBP;EACA,2BAAA;GApBE,GAAG;GACH,UAAU,EAAW,4CACnB,EAAW,CAAa,GACxB,EACF;GACA,eAAe,EAAgB,CAAa;GAC5C,SACE,MAC2C;IAC3C,IAAM,IAAS,EAAK,EAAK,gBAAgB,CAAC,GAAG,aAAa;IAI1D,OAAO,IAAe;KAAE,GAAG;KAAQ;IAAa,IAAI;GACtD;EAMF;CACF;AACF;AAaA,SAAgB,EACd,GACA,GAC2C;CAC3C,IAAM,EAAE,qBAAkB,EAAkB;CAE5C,OAAO,EACL,OAAO,MAA0C;EAC/C,IAAI,CAAC,GAAuB,OAAO,CAAC;EACpC,IAAM,IAAU,EAAW,KAAK;EAChC,IAAI,CAAC,GAAS,OAAO,CAAC;EACtB,IAAM,IACJ,MAAM,EAAc,+BAA+B,6BACjD,EACE,kBAAkB;GAChB,cACE;GACF;GACA,aAAa;IACX,WAAW;IACX,aAAa,CAAC,CAAqB;IACnC,cAAc,CAAC,CAAqB;GACtC;EACF,EACF,CACF,GACI,IAAwB,CAAC;EAC/B,KAAK,IAAM,KAAO,EAAQ,QAAQ,CAAC,GACjC,KAAK,IAAM,KAAS,EAAI,UAAU,CAAC,GACjC,AAAI,EAAM,SACR,EAAY,KAAK,EAAM,KAAK;EAIlC,OAAO;CACT,GACA;EAAC;EAAe;EAAe;CAAqB,CACtD;AACF;AAOA,SAAgB,EACd,GACA,GACA,GACiC;CACjC,IAAM,EAAE,eAAY,mBAAgB,EAAkB,GAEhD,EAAE,MAAM,MAAiB,EAAmB,GAAW,KAAA,GAAW,EACtE,oBAAoB,GACtB,CAAC,GACK,IAAe,GAAc,aAAa;CAEhD,OAAO,QAEH,EACE,GACA,GACA,GACA,GACA,CACF,GACF;EAAC;EAAY;EAAa;EAAoB;EAAe;CAAY,CAC3E;AACF"}
1
+ {"version":3,"file":"SearchQueryUseQueryOptions.js","names":[],"sources":["../../../src/components/SearchQueryWrapper/SearchQueryUseQueryOptions.ts"],"sourcesContent":["import * as SynapseClient from '@/synapse-client/SynapseClient'\nimport { tableQueryUseQueryDefaults } from '@/synapse-queries'\nimport { useGetEntityBundle } from '@/synapse-queries/entity/useEntityBundle'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport {\n AsynchronousJobStatus,\n ColumnModel,\n FACET_COLUMN_RANGE_REQUEST_CONCRETE_TYPE_VALUE,\n FacetColumnRangeRequest,\n FacetColumnResultRange,\n FacetColumnResultValues,\n FACET_COLUMN_VALUES_REQUEST_CONCRETE_TYPE_VALUE,\n FacetColumnValuesRequest,\n QueryBundleRequest,\n QueryResultBundle,\n RowSet,\n SortItem,\n TEXT_MATCHES_QUERY_FILTER_CONCRETE_TYPE_VALUE,\n TextMatchesQueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport type {\n Aggregation,\n DslQuery,\n SearchIndexQuery,\n SearchQueryResults,\n SearchSearchQuery,\n SynapseClientError,\n TermsAggregation,\n} from '@sage-bionetworks/synapse-client'\nimport {\n InfiniteData,\n QueryKey,\n UseInfiniteQueryOptions,\n UseSuspenseQueryOptions,\n} from '@tanstack/react-query'\nimport { omit } from 'lodash-es'\nimport dayjs from 'dayjs'\nimport { useCallback, useMemo } from 'react'\nimport { KeyFactory } from '@/synapse-queries/KeyFactory'\n\n// ─── Local OpenSearch DSL types ─────────────────────────────────────────────\n// Narrow typings for the OpenSearch structures we build (query DSL, sort) and\n// parse (aggregation results). These are intentionally minimal – only the fields\n// we actually produce/consume are declared. Aggregation types use the generated\n// Aggregation/TermsAggregation types from @sage-bionetworks/synapse-client.\n\ntype FilterClause =\n | { terms: Record<string, string[]> }\n | { range: Record<string, { gte?: string; lte?: string }> }\n\ntype MultiMatchClause = { multi_match: { query: string; fuzziness: string } }\n\ntype BoolQuery = {\n bool: {\n must?: [MultiMatchClause]\n filter?: FilterClause[]\n }\n}\n\ntype SearchQueryDSL =\n | MultiMatchClause\n | { match_all: Record<never, never> }\n | BoolQuery\n\ntype OpenSearchBucket = { key: unknown; doc_count: number }\ntype OpenSearchTermsAgg = { buckets?: OpenSearchBucket[] }\n\n/**\n * TanStack Query options for the SearchQueryServicesApi, mirroring TableQueryUseQueryOptions\n * but parameterised over SearchIndexQuery rather than QueryBundleRequest. This eliminates\n * `as unknown as` casts inside the implementation. A single cast to TableQueryUseQueryOptions\n * is still required at the boundary where SearchQueryWrapper assigns these into QueryContextType.\n */\nexport type SearchTableQueryUseQueryOptions = {\n rowDataQueryOptions: UseSuspenseQueryOptions<\n AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n SynapseClientError,\n RowSet | undefined\n >\n rowDataInfiniteQueryOptions: UseInfiniteQueryOptions<\n AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n SynapseClientError,\n InfiniteData<AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>>,\n QueryKey,\n string | number | undefined\n >\n queryMetadataQueryOptions: UseSuspenseQueryOptions<\n AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n SynapseClientError,\n Omit<QueryResultBundle, 'queryResult'>\n >\n}\n\nexport function getNextPageParamForSearchQueryResults(\n lastPage: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n allPages: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>[],\n): number | string | undefined {\n const rowsInLastPage =\n lastPage.responseBody?.queryResult?.queryResults.rows?.length ?? 0\n const requestedPageSize = lastPage.requestBody?.searchQuery?.size\n const totalRows = lastPage.responseBody?.queryCount\n const fetchedRows = allPages.reduce(\n (acc, page) =>\n acc + (page.responseBody?.queryResult?.queryResults.rows?.length ?? 0),\n 0,\n )\n\n if (rowsInLastPage === 0) {\n return undefined\n }\n\n // A short page means we've reached the end, even when total hits is missing or stale.\n if (requestedPageSize != null && rowsInLastPage < requestedPageSize) {\n return undefined\n }\n\n if (totalRows != null && fetchedRows >= totalRows) {\n return undefined\n }\n\n return fetchedRows\n}\n\n/**\n * Converts a QueryBundleRequest (used internally for state management) into a SearchIndexQuery\n * that can be sent to the SearchQueryServicesApi.\n *\n * Mapping:\n * - columnModels (facetType 'enumeration') → aggregations (OpenSearch terms aggregations)\n * - query.selectedFacets (enumeration) → query.bool.filter terms clauses\n * - query.selectedFacets (range) → query.bool.filter range clauses\n * - query.additionalFilters (TextMatchesQueryFilter) → multi_match query clause\n * - query.sort → sort (SortItem { column, direction } → [{ column: 'asc'|'desc' }])\n * - query.limit → size\n * - query.offset → from\n * - partMask → dropped (SearchIndexQuery has no bitmask concept)\n */\nexport function toSearchIndexQuery(\n queryBundleRequest: QueryBundleRequest,\n searchIndexId: string,\n columnModels?: ColumnModel[],\n): SearchIndexQuery {\n // Build aggregations from ColumnModels that have facetType 'enumeration'.\n // Range columns are excluded: we synthesize FacetColumnResultRange entries client-side.\n const aggregationEntries = columnModels\n ?.filter(cm => cm.facetType === 'enumeration')\n .map(cm => {\n const termsAgg: TermsAggregation = { field: cm.name, size: 100 }\n if (cm.facetSortConfig?.property != null) {\n // Map FacetColumnSortProperty ('VALUE'|'FREQUENCY') → OpenSearch order key ('_key'|'_count')\n const orderKey =\n cm.facetSortConfig.property === 'VALUE' ? '_key' : '_count'\n const orderDir =\n cm.facetSortConfig.direction === 'DESC' ? 'desc' : 'asc'\n termsAgg.order = { [orderKey]: orderDir }\n }\n return [cm.name, { terms: termsAgg }] as [string, Aggregation]\n })\n const aggregations =\n aggregationEntries && aggregationEntries.length > 0\n ? Object.fromEntries(aggregationEntries)\n : undefined\n\n // Build filter clauses from enumeration selectedFacets\n const filterClauses: FilterClause[] = []\n\n queryBundleRequest.query.selectedFacets\n ?.filter(\n (f): f is FacetColumnValuesRequest =>\n f.concreteType === FACET_COLUMN_VALUES_REQUEST_CONCRETE_TYPE_VALUE,\n )\n .forEach(f => {\n filterClauses.push({ terms: { [f.columnName]: f.facetValues ?? [] } })\n })\n\n // Build range filter clauses from range selectedFacets.\n // DATE columns: the Range UI emits formatted dates (\"YYYY-MM-DD\") but OpenSearch\n // expects unix millisecond timestamps. Convert here.\n queryBundleRequest.query.selectedFacets\n ?.filter(\n (f): f is FacetColumnRangeRequest =>\n f.concreteType === FACET_COLUMN_RANGE_REQUEST_CONCRETE_TYPE_VALUE,\n )\n .forEach(f => {\n const columnType = columnModels?.find(\n cm => cm.name === f.columnName,\n )?.columnType\n const toApiValue = (v: string | undefined): string | undefined => {\n if (!v || columnType !== 'DATE') return v\n // Convert \"YYYY-MM-DD\" → unix ms; leave already-numeric values untouched\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(v)) {\n return String(dayjs(v).valueOf())\n }\n return v\n }\n const rangeClause: { gte?: string; lte?: string } = {}\n const min = toApiValue(f.min)\n const max = toApiValue(f.max)\n if (min !== undefined) rangeClause.gte = min\n if (max !== undefined) rangeClause.lte = max\n filterClauses.push({ range: { [f.columnName]: rangeClause } })\n })\n\n // Extract queryText by concatenating all TextMatchesQueryFilter searchExpression values\n const textMatchesExpressions = queryBundleRequest.query.additionalFilters\n ?.filter(\n (f): f is TextMatchesQueryFilter =>\n f.concreteType === TEXT_MATCHES_QUERY_FILTER_CONCRETE_TYPE_VALUE,\n )\n .map(f => f.searchExpression)\n .filter((expr): expr is string => expr != null && expr.length > 0)\n const queryText =\n textMatchesExpressions && textMatchesExpressions.length > 0\n ? textMatchesExpressions.join(' ')\n : undefined\n\n // Build the OpenSearch query DSL\n let query: SearchQueryDSL\n if (queryText && filterClauses.length > 0) {\n query = {\n bool: {\n must: [{ multi_match: { query: queryText, fuzziness: 'AUTO' } }],\n filter: filterClauses,\n },\n }\n } else if (queryText) {\n query = { multi_match: { query: queryText, fuzziness: 'AUTO' } }\n } else if (filterClauses.length > 0) {\n query = { bool: { filter: filterClauses } }\n } else {\n query = { match_all: {} }\n }\n\n // Map SortItem[] → OpenSearch sort shape: [{ columnName: 'asc'|'desc' }, ...]\n // filtering out entries with no direction (which mean \"remove sort\").\n const sortEntries = queryBundleRequest.query.sort\n ?.filter(\n (s): s is SortItem & { direction: 'ASC' | 'DESC' } =>\n s.direction === 'ASC' || s.direction === 'DESC',\n )\n .map(s => ({ [s.column]: s.direction.toLowerCase() }))\n\n const searchQuery: SearchSearchQuery = {\n query: query as unknown as DslQuery,\n aggregations,\n sort: sortEntries?.length ? sortEntries : undefined,\n size: queryBundleRequest.query.limit,\n from: queryBundleRequest.query.offset,\n }\n\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.search.table.SearchIndexQuery' as const,\n searchIndexId,\n searchQuery,\n }\n}\n\n/**\n * Converts a SearchQueryResults (the actual API response) into a QueryResultBundle\n * so that existing subcomponents (FacetFilterControls, RowSetView, etc.) work unchanged.\n *\n * Mapping:\n * - totalHits → queryCount\n * - hits → queryResult.queryResults (rows derived from hit.rowId/rowVersion/fields)\n * - aggregationResults → facets (parsed from opaque OpenSearch aggregation JSON)\n */\nexport function searchQueryResultsToQueryResultBundle(\n results: SearchQueryResults | undefined,\n query: SearchIndexQuery,\n columnModels?: ColumnModel[],\n selectedFacets?: (FacetColumnValuesRequest | FacetColumnRangeRequest)[],\n): QueryResultBundle {\n if (!results) {\n return {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryResultBundle',\n }\n }\n\n // Derive column names from the server-returned selectColumns. Both the row data\n // query and the metadata query request SELECT_COLUMNS, so this is always present.\n const fieldNames: string[] =\n results.selectColumns\n ?.map(col => col.name)\n .filter((n): n is string => !!n) ?? []\n\n const headers = fieldNames.map(name => ({\n name,\n columnType:\n columnModels?.find(cm => cm.name === name)?.columnType ??\n ('STRING' as const),\n }))\n\n const rows = (results.hits ?? []).map(hit => ({\n rowId: hit.rowId,\n versionNumber: hit.rowVersion,\n values: fieldNames.map(name => {\n return hit.fields?.find(f => f.name === name)?.value ?? null\n }),\n }))\n\n const queryResult =\n headers.length > 0 || rows.length > 0\n ? {\n concreteType:\n 'org.sagebionetworks.repo.model.table.QueryResult' as const,\n queryResults: {\n concreteType:\n 'org.sagebionetworks.repo.model.table.RowSet' as const,\n tableId: query.searchIndexId ?? '',\n etag: '',\n headers,\n rows,\n },\n }\n : undefined\n\n // Parse aggregationResults (opaque OpenSearch terms aggregation JSON) into\n // FacetColumnResultValues. Each key in aggregationResults corresponds to a column name\n // whose aggregation was requested in toSearchIndexQuery. The value is an OpenSearch\n // terms aggregation response: { buckets: [{ key: unknown, doc_count: number }] }.\n // We cast once via `unknown` to attach our narrow local type and avoid unsafe-access lint.\n const aggregationResults = results.aggregationResults as unknown as Record<\n string,\n OpenSearchTermsAgg\n > | null\n const rawFacets: FacetColumnResultValues[] = Object.entries(\n aggregationResults ?? {},\n ).map(([columnName, agg]) => {\n const selectedValues =\n selectedFacets\n ?.filter(\n (f): f is FacetColumnValuesRequest =>\n f.concreteType ===\n FACET_COLUMN_VALUES_REQUEST_CONCRETE_TYPE_VALUE &&\n f.columnName === columnName,\n )\n .flatMap(f => f.facetValues ?? []) ?? []\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.table.FacetColumnResultValues' as const,\n facetType: 'enumeration' as const,\n columnName,\n facetValues: (agg.buckets ?? []).map(b => ({\n value: String(b.key),\n count: b.doc_count,\n isSelected: selectedValues.includes(String(b.key)),\n })),\n }\n })\n\n // Synthesize FacetColumnResultRange for range-type DATE/DOUBLE/INTEGER columns. The Search\n // API's aggregations only produce terms (enumeration) results; range stats are unavailable\n // server-side. columnMin/columnMax are left empty; selectedMin/selectedMax are taken\n // directly from selectedFacets so any applied range filter is still reflected in the UI.\n // Note: for INTEGER columns the RangeSlider requires real bounds, so the UI falls back to a\n // plain Range number input when columnMin/columnMax are absent.\n const syntheticRangeFacets: FacetColumnResultRange[] = (columnModels ?? [])\n .filter(\n cm =>\n cm.facetType === 'range' &&\n (cm.columnType === 'DATE' ||\n cm.columnType === 'DOUBLE' ||\n cm.columnType === 'INTEGER') &&\n !rawFacets.some(f => f.columnName === cm.name),\n )\n .map(cm => {\n const rangeFilter = selectedFacets?.find(\n (f): f is FacetColumnRangeRequest =>\n f.concreteType === FACET_COLUMN_RANGE_REQUEST_CONCRETE_TYPE_VALUE &&\n f.columnName === cm.name,\n )\n return {\n concreteType:\n 'org.sagebionetworks.repo.model.table.FacetColumnResultRange' as const,\n facetType: 'range' as const,\n columnName: cm.name,\n columnMin: '',\n columnMax: '',\n selectedMin: rangeFilter?.min,\n selectedMax: rangeFilter?.max,\n }\n })\n\n const allFacets: NonNullable<QueryResultBundle['facets']> = [\n ...(rawFacets ?? []),\n ...syntheticRangeFacets,\n ]\n\n // Reorder all facets to match the columnModels order so downstream components\n // (e.g. FacetFilterControls) render facets in the expected column order.\n const orderedFacets: QueryResultBundle['facets'] = columnModels\n ? [\n ...allFacets\n .filter(f => columnModels.some(cm => cm.name === f.columnName))\n .sort(\n (a, b) =>\n columnModels.findIndex(cm => cm.name === a.columnName) -\n columnModels.findIndex(cm => cm.name === b.columnName),\n ),\n ...allFacets.filter(\n f => !columnModels.some(cm => cm.name === f.columnName),\n ),\n ]\n : allFacets\n\n return {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryResultBundle',\n queryCount: results.totalHits,\n selectColumns: headers,\n queryResult,\n facets: orderedFacets,\n }\n}\n\nexport function getSearchQueryUseQueryOptions(\n queryBundleRequest: QueryBundleRequest,\n keyFactory: KeyFactory,\n accessToken: string | undefined,\n searchIndexId: string,\n columnModels?: ColumnModel[],\n): SearchTableQueryUseQueryOptions {\n const baseQuery: SearchIndexQuery = toSearchIndexQuery(\n queryBundleRequest,\n searchIndexId,\n columnModels,\n )\n const rowDataQuery: SearchIndexQuery = {\n ...baseQuery,\n searchQuery: {\n ...baseQuery.searchQuery,\n // Omit aggregations from the row data query: facet aggregations are only needed\n // in the metadata query. Removing them here keeps the row data query key stable\n // while column models are loading, preventing an unnecessary re-fetch (and a brief\n // loading flash) when column models first arrive.\n aggregations: undefined,\n },\n // Request SELECT_COLUMNS so headers are available for row rendering.\n // HITS is returned by default even when responseParts is specified.\n responseParts: new Set(['HITS', 'SELECT_COLUMNS'] as const),\n }\n const metadataQuery: SearchIndexQuery = {\n ...baseQuery,\n // Request all opt-in parts needed for the metadata response:\n // TOTAL_HITS → queryCount (drives tab count / spinner resolution)\n // SELECT_COLUMNS → column headers for the table\n // Aggregation results are returned automatically when aggregations is set on the query.\n responseParts: new Set(['TOTAL_HITS', 'SELECT_COLUMNS'] as const),\n }\n\n // Convert responseParts Set → sorted array for query key building.\n // JSON.stringify(new Set([...])) === '{}', so two queries whose only difference is\n // their responseParts would hash to the same key and share a cache entry.\n // Using a sorted array gives each query a distinct, stable key.\n const toKeyShape = (query: SearchIndexQuery) => ({\n ...query,\n responseParts: query.responseParts\n ? [...query.responseParts].sort()\n : undefined,\n })\n\n // Fetches from the SearchQueryServicesApi and converts the SearchQueryResults responseBody\n // into QueryResultBundle shape. This allows all downstream shared components\n // (UseRowSet, QueryVisualizationWrapper, etc.) to access data.responseBody.*\n // using the same patterns as regular table queries (queryResult.queryResults, selectColumns, etc.).\n const fetchAndConvert = async (query: SearchIndexQuery) => {\n const asyncStatus = await SynapseClient.getSearchQueryAsyncJobResults(\n query,\n accessToken,\n )\n return {\n ...asyncStatus,\n responseBody: searchQueryResultsToQueryResultBundle(\n asyncStatus.responseBody,\n query,\n columnModels,\n queryBundleRequest.query.selectedFacets as\n | (FacetColumnValuesRequest | FacetColumnRangeRequest)[]\n | undefined,\n ),\n }\n }\n\n // `as unknown as` is necessary because SearchIndexQuery.responseParts is a Set but\n // toKeyShape converts it to a sorted string[] for stable cache key serialisation.\n const rowDataQueryOptions: SearchTableQueryUseQueryOptions['rowDataQueryOptions'] =\n {\n ...tableQueryUseQueryDefaults,\n queryKey: keyFactory.getSearchQueryResultWithAsyncStatusQueryKey(\n toKeyShape(rowDataQuery) as unknown as SearchIndexQuery,\n false,\n ),\n queryFn: () => fetchAndConvert(rowDataQuery),\n select: (\n data: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n ): RowSet | undefined => data.responseBody?.queryResult?.queryResults,\n }\n\n const rowDataInfiniteQueryOptions: SearchTableQueryUseQueryOptions['rowDataInfiniteQueryOptions'] =\n {\n ...tableQueryUseQueryDefaults,\n queryKey: keyFactory.getSearchQueryResultWithAsyncStatusQueryKey(\n toKeyShape(rowDataQuery) as unknown as SearchIndexQuery,\n true,\n ),\n initialPageParam: 0 as number | string | undefined,\n getNextPageParam: (\n lastPage: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n allPages: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>[],\n ): number | string | undefined => {\n return getNextPageParamForSearchQueryResults(lastPage, allPages)\n },\n queryFn: (context: { pageParam?: number | string }) => {\n const offset =\n typeof context.pageParam === 'string'\n ? parseInt(context.pageParam)\n : (context.pageParam ?? 0)\n const requestForPage: SearchIndexQuery = {\n ...rowDataQuery,\n searchQuery: {\n ...rowDataQuery.searchQuery,\n from: offset,\n },\n }\n return fetchAndConvert(requestForPage)\n },\n select: (\n data: InfiniteData<\n AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>\n >,\n ) => data,\n }\n\n const queryMetadataQueryOptions: SearchTableQueryUseQueryOptions['queryMetadataQueryOptions'] =\n {\n ...tableQueryUseQueryDefaults,\n queryKey: keyFactory.getSearchQueryResultWithAsyncStatusQueryKey(\n toKeyShape(metadataQuery) as unknown as SearchIndexQuery,\n false,\n ),\n queryFn: () => fetchAndConvert(metadataQuery),\n select: (\n data: AsynchronousJobStatus<SearchIndexQuery, QueryResultBundle>,\n ): Omit<QueryResultBundle, 'queryResult'> => {\n const result = omit(data.responseBody ?? {}, 'queryResult') as Omit<\n QueryResultBundle,\n 'queryResult'\n >\n return columnModels ? { ...result, columnModels } : result\n },\n }\n\n return {\n rowDataQueryOptions,\n rowDataInfiniteQueryOptions,\n queryMetadataQueryOptions,\n }\n}\n\n/**\n * Returns a stable callback that fetches autocomplete suggestions for a search input\n * using the synchronous `POST /search/autocomplete` endpoint.\n *\n * The query is built from the current `searchIndexId` and `autocompleteFieldName`:\n * - `searchQuery.query` is a `match_bool_prefix` clause scoped to `autocompleteFieldName`\n * - `searchQuery._source` is set to `[autocompleteFieldName]` so only that field is returned\n *\n * When `autocompleteFieldName` is undefined, the returned callback immediately returns `[]`.\n */\nexport function useGetSuggestionsForSearchIndex(\n searchIndexId: string,\n autocompleteFieldName: string | undefined,\n): (searchText: string) => Promise<string[]> {\n const { synapseClient } = useSynapseContext()\n\n return useCallback(\n async (searchText: string): Promise<string[]> => {\n if (!autocompleteFieldName) return []\n const trimmed = searchText.trim()\n if (!trimmed) return []\n const results =\n await synapseClient.searchManagementServicesClient.postRepoV1SearchAutocomplete(\n {\n searchAutocompleteRequest: {\n searchIndexId,\n searchQuery: {\n query: {\n match_bool_prefix: {\n [autocompleteFieldName]: { query: trimmed },\n },\n },\n _source: { includes: [autocompleteFieldName] },\n },\n },\n },\n )\n const suggestions: string[] = []\n for (const hit of results.hits ?? []) {\n for (const field of hit.fields ?? []) {\n if (field.value) {\n suggestions.push(field.value)\n }\n }\n }\n return suggestions\n },\n [synapseClient, searchIndexId, autocompleteFieldName],\n )\n}\n\n/**\n * Returns TanStack Query options that call the SearchQueryServicesApi (instead of the\n * standard Table Query API) but return data in the same QueryResultBundle format, allowing\n * all existing subcomponents (FacetFilterControls, RowSetView, etc.) to work unchanged.\n */\nexport function useSearchQueryUseQueryOptions(\n queryBundleRequest: QueryBundleRequest,\n searchIndexId: string,\n synapseId?: string,\n): SearchTableQueryUseQueryOptions {\n const { keyFactory, accessToken } = useSynapseContext()\n\n const { data: entityBundle } = useGetEntityBundle(synapseId, undefined, {\n includeTableBundle: true,\n })\n const columnModels = entityBundle?.tableBundle?.columnModels\n\n return useMemo(\n () =>\n getSearchQueryUseQueryOptions(\n queryBundleRequest,\n keyFactory,\n accessToken,\n searchIndexId,\n columnModels,\n ),\n [keyFactory, accessToken, queryBundleRequest, searchIndexId, columnModels],\n )\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"TopLevelControls.d.ts","sourceRoot":"","sources":["../../../../src/components/SynapseTable/TopLevelControls/TopLevelControls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,EAEL,kBAAkB,EAClB,iBAAiB,EACjB,GAAG,EAEJ,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EAAE,SAAS,EAAqB,MAAM,OAAO,CAAA;AA6BpD,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,cAAc,CAAC,EAAE,aAAa,EAAE,CAAA;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,CAAC,GAAG,SAAS,CAAA;IACjE,YAAY,EAAE,GAAG,EAAE,GAAG,SAAS,CAAA;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC7B,CAAA;AAGD,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,IAAI,CAAA;IACnD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,KAAG,KAAK,CAAC,SAoS9D,CAAA;AAED,eAAe,gBAAgB,CAAA"}
1
+ {"version":3,"file":"TopLevelControls.d.ts","sourceRoot":"","sources":["../../../../src/components/SynapseTable/TopLevelControls/TopLevelControls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAIzB,OAAO,EACL,kBAAkB,EAClB,iBAAiB,EACjB,GAAG,EAEJ,MAAM,iCAAiC,CAAA;AAGxC,OAAO,EAAE,SAAS,EAAY,MAAM,OAAO,CAAA;AA4B3C,MAAM,MAAM,qBAAqB,GAAG;IAClC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,yBAAyB,CAAC,EAAE,OAAO,CAAA;IACnC,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAC9B,cAAc,CAAC,EAAE,aAAa,EAAE,CAAA;IAChC,mBAAmB,CAAC,EAAE,OAAO,CAAA;IAC7B,yBAAyB,CAAC,EAAE,MAAM,CAAA;IAClC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,OAAO,GAAG;IACpB,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,IAAI,CAAC,iBAAiB,EAAE,aAAa,CAAC,GAAG,SAAS,CAAA;IACjE,YAAY,EAAE,GAAG,EAAE,GAAG,SAAS,CAAA;IAC/B,OAAO,EAAE,MAAM,IAAI,CAAA;IACnB,OAAO,CAAC,EAAE,kBAAkB,CAAA;CAC7B,CAAA;AAGD,MAAM,MAAM,aAAa,GAAG;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,CAAC,KAAK,EAAE,yBAAyB,KAAK,IAAI,CAAA;IACnD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,QAAA,MAAM,gBAAgB,GAAI,OAAO,qBAAqB,KAAG,KAAK,CAAC,SA+Q9D,CAAA;AAED,eAAe,gBAAgB,CAAA"}
@@ -2,18 +2,17 @@ import "../../../utils/SynapseConstants.js";
2
2
  import { copyStringToClipboard as e } from "../../../utils/functions/StringUtils.js";
3
3
  import { useSynapseContext as t } from "../../../utils/context/SynapseContext.js";
4
4
  import "../../../utils/index.js";
5
- import { useGetEntity as ee } from "../../../synapse-queries/entity/useEntity.js";
5
+ import { useGetEntity as n } from "../../../synapse-queries/entity/useEntity.js";
6
6
  import "../../../synapse-queries/index.js";
7
- import n from "../../IconSvg/index.js";
7
+ import r from "../../IconSvg/index.js";
8
8
  import "../SynapseTableUtils.js";
9
- import { useQueryContext as r } from "../../QueryContext/QueryContext.js";
9
+ import { useQueryContext as ee } from "../../QueryContext/QueryContext.js";
10
10
  import "../../QueryContext/index.js";
11
- import { useGetQueryMetadata as te } from "../../QueryWrapper/useGetQueryMetadata.js";
12
- import { useQueryVisualizationContext as i } from "../../QueryVisualizationWrapper/QueryVisualizationContext.js";
11
+ import { useGetQueryMetadata as i } from "../../QueryWrapper/useGetQueryMetadata.js";
12
+ import { useQueryVisualizationContext as a } from "../../QueryVisualizationWrapper/QueryVisualizationContext.js";
13
13
  import "../../QueryVisualizationWrapper/index.js";
14
- import { isRowSelectionVisibleAtom as a, useHasSelectedRowsAtomValue as o, useSelectedRowsAtomValue as s } from "../../QueryWrapper/TableRowSelectionState.js";
15
- import { SignInRequiredModal as c } from "../../SignInRequiredModal/SignInRequiredModal.js";
16
- import { QueryCount as l } from "../../QueryCount/QueryCount.js";
14
+ import { isRowSelectionVisibleAtom as o, useHasSelectedRowsAtomValue as s, useSelectedRowsAtomValue as c } from "../../QueryWrapper/TableRowSelectionState.js";
15
+ import { SignInRequiredModal as l } from "../../SignInRequiredModal/SignInRequiredModal.js";
17
16
  import u from "../../MissingQueryResultsWarning/MissingQueryResultsWarning.js";
18
17
  import { ElementWithTooltip as d } from "../../widgets/ElementWithTooltip.js";
19
18
  import { getNumberOfResultsToInvokeAction as f, getNumberOfResultsToInvokeActionCopy as p } from "./TopLevelControlsUtils.js";
@@ -21,46 +20,36 @@ import m from "../export/ExportToAnalysisPlatformDialog.js";
21
20
  import { CustomControlButton as h } from "../CustomControls/CustomControlButton.js";
22
21
  import { RowSelectionControls as g } from "../RowSelection/RowSelectionControls.js";
23
22
  import { DownloadOptions as _ } from "../table-top/DownloadOptions.js";
24
- import { ColumnSelection as ne } from "../table-top/ColumnSelection.js";
23
+ import { ColumnSelection as v } from "../table-top/ColumnSelection.js";
25
24
  import "../table-top/index.js";
26
- import { useMemo as re, useState as v } from "react";
27
- import { cloneDeep as ie } from "lodash-es";
28
- import { Button as y, Divider as ae, Tooltip as oe, Typography as b } from "@mui/material";
29
- import { Fragment as x, jsx as S, jsxs as C } from "react/jsx-runtime";
30
- import { useAtomValue as w } from "jotai";
25
+ import { useState as y } from "react";
26
+ import { cloneDeep as te } from "lodash-es";
27
+ import { Button as b, Divider as ne, Tooltip as x, Typography as S } from "@mui/material";
28
+ import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
29
+ import { useAtomValue as E } from "jotai";
31
30
  //#region src/components/SynapseTable/TopLevelControls/TopLevelControls.tsx
32
- var T = "SendToAnalysisPlatformTopLevelControlButton", E = (E) => {
33
- let [D, O] = v(!1), { isAuthenticated: k } = t(), { name: A, showColumnSelection: j = !1, hideDownload: M = !1, hideVisualizationsControl: N = !1, hideFacetFilterControl: P = !1, hideQueryCount: F = !1, hideSqlEditorControl: I = !0, customControls: L, cavaticaConnectAccountURL: R, remount: z } = E, { entityId: B, versionNumber: V, getInitQueryRequest: H, getCurrentQueryRequest: U, hasResettableFilters: se } = r(), { data: W } = ee(B, V), { data: G } = te(), { lockedColumn: K } = r(), q = w(a), J = s(), Y = o(), { setShowSearchBar: ce, columnsToShowInTable: X, setColumnsToShowInTable: le, enabledExternalAnalysisPlatforms: ue, setIsShowingExportToAnalysisPlatformModal: de, unitDescription: fe, setShowDownloadConfirmation: pe, showCopyToClipboard: me, hideSearchBarControl: he, setShowPlots: Z, setShowSqlEditor: ge, showFacetFilter: Q, setShowFacetFilter: _e } = i(), ve = ue.length > 0, [ye, $] = v(!1), be = re(() => {
34
- let e = H();
35
- return {
36
- sql: e.query.sql,
37
- selectedFacets: (e.query.selectedFacets ?? []).filter((e) => e.columnName === K?.columnName),
38
- additionalFilters: (e.query.additionalFilters ?? []).filter((e) => "columnName" in e ? e.columnName === K?.columnName : !0)
39
- };
40
- }, [H, K?.columnName]), xe = (e) => {
41
- let t = ie(X);
42
- t.includes(e) ? t = t.filter((t) => t !== e) : t.push(e), le(t);
43
- }, Se = f(Y, J, G?.queryCount), Ce = p(se, Y, J, G?.queryCount, fe);
44
- return /* @__PURE__ */ S("div", {
31
+ var D = "SendToAnalysisPlatformTopLevelControlButton", O = (O) => {
32
+ let [k, A] = y(!1), { isAuthenticated: j } = t(), { name: M, showColumnSelection: N = !1, hideDownload: P = !1, hideVisualizationsControl: F = !1, hideFacetFilterControl: I = !1, hideQueryCount: L = !1, hideSqlEditorControl: R = !0, customControls: z, cavaticaConnectAccountURL: B, remount: V } = O, { entityId: H, versionNumber: U, getCurrentQueryRequest: W, hasResettableFilters: re } = ee(), { data: G } = n(H, U), { data: K } = i(), q = E(o), J = c(), Y = s(), { setShowSearchBar: X, columnsToShowInTable: Z, setColumnsToShowInTable: ie, enabledExternalAnalysisPlatforms: ae, setIsShowingExportToAnalysisPlatformModal: oe, unitDescription: se, setShowDownloadConfirmation: ce, showCopyToClipboard: le, hideSearchBarControl: ue, setShowPlots: de, setShowSqlEditor: fe, showFacetFilter: Q, setShowFacetFilter: pe } = a(), me = ae.length > 0, [he, $] = y(!1), ge = (e) => {
33
+ let t = te(Z);
34
+ t.includes(e) ? t = t.filter((t) => t !== e) : t.push(e), ie(t);
35
+ }, _e = f(Y, J, K?.queryCount), ve = p(re, Y, J, K?.queryCount, se), ye = !L && K?.queryCount !== void 0 ? `(${K.queryCount.toLocaleString()})` : null;
36
+ return /* @__PURE__ */ w("div", {
45
37
  className: "TopLevelControls",
46
38
  "data-testid": "TopLevelControls",
47
- children: /* @__PURE__ */ C("div", { children: [/* @__PURE__ */ C("div", {
39
+ children: /* @__PURE__ */ T("div", { children: [/* @__PURE__ */ T("div", {
48
40
  className: "TopLevelControls__querycount",
49
- children: [A && /* @__PURE__ */ C(x, { children: [/* @__PURE__ */ C(b, {
41
+ children: [M && /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ T(S, {
50
42
  variant: "sectionTitle",
51
43
  role: "heading",
52
44
  children: [
53
- A,
45
+ M,
54
46
  " ",
55
- !F && /* @__PURE__ */ S(l, {
56
- query: be,
57
- parens: !0
58
- })
47
+ ye
59
48
  ]
60
- }), !F && W && /* @__PURE__ */ S(u, { entity: W })] }), !P && /* @__PURE__ */ C(y, {
49
+ }), !L && G && /* @__PURE__ */ w(u, { entity: G })] }), !I && /* @__PURE__ */ T(b, {
61
50
  variant: "text",
62
- onClick: () => _e((e) => !e),
63
- startIcon: /* @__PURE__ */ S(n, {
51
+ onClick: () => pe((e) => !e),
52
+ startIcon: /* @__PURE__ */ w(r, {
64
53
  icon: Q ? "close" : "filter",
65
54
  wrap: !1
66
55
  }),
@@ -72,48 +61,48 @@ var T = "SendToAnalysisPlatformTopLevelControlButton", E = (E) => {
72
61
  },
73
62
  children: [Q ? "Hide" : "Show", " filters"]
74
63
  })]
75
- }), /* @__PURE__ */ C("div", {
64
+ }), /* @__PURE__ */ T("div", {
76
65
  className: "TopLevelControls__actions",
77
66
  children: [
78
- ve && /* @__PURE__ */ C(x, { children: [/* @__PURE__ */ S(oe, {
79
- title: /* @__PURE__ */ C(x, { children: [
67
+ me && /* @__PURE__ */ T(C, { children: [/* @__PURE__ */ w(x, {
68
+ title: /* @__PURE__ */ T(C, { children: [
80
69
  "This action will send a reference to",
81
70
  " ",
82
71
  Y ? "each selected file" : "every file in the current table",
83
72
  " ",
84
73
  "to a chosen external analysis platform.",
85
74
  " ",
86
- !Y && Q && /* @__PURE__ */ S(x, { children: "You can change what is sent by applying filters using the controls in the sidebar." }),
87
- Y && /* @__PURE__ */ S(x, { children: "You can change what is sent by selecting a different set of files." })
75
+ !Y && Q && /* @__PURE__ */ w(C, { children: "You can change what is sent by applying filters using the controls in the sidebar." }),
76
+ Y && /* @__PURE__ */ w(C, { children: "You can change what is sent by selecting a different set of files." })
88
77
  ] }),
89
- children: /* @__PURE__ */ C(y, {
78
+ children: /* @__PURE__ */ T(b, {
90
79
  variant: "text",
91
- disabled: !Se,
92
- onClick: () => k ? de(!0) : O(!0),
93
- id: T,
80
+ disabled: !_e,
81
+ onClick: () => j ? oe(!0) : A(!0),
82
+ id: D,
94
83
  children: [
95
84
  "Send ",
96
- Ce,
85
+ ve,
97
86
  " to Analysis Platform"
98
87
  ]
99
88
  })
100
- }), /* @__PURE__ */ S(ae, {
89
+ }), /* @__PURE__ */ w(ne, {
101
90
  orientation: "vertical",
102
91
  variant: "middle",
103
92
  flexItem: !0
104
93
  })] }),
105
- D && /* @__PURE__ */ S(c, {
106
- onHide: () => O(!1),
94
+ k && /* @__PURE__ */ w(l, {
95
+ onHide: () => A(!1),
107
96
  content: "You must be signed in to send results to an analysis platform."
108
97
  }),
109
- !he && /* @__PURE__ */ S(d, {
98
+ !ue && /* @__PURE__ */ w(d, {
110
99
  tooltipText: "Show / Hide Search Bar",
111
- callbackFn: () => ce((e) => !e),
100
+ callbackFn: () => X((e) => !e),
112
101
  darkTheme: !0,
113
102
  icon: "search"
114
103
  }),
115
- me && /* @__PURE__ */ S(d, {
116
- tooltipText: ye ? "Copied to clipboard" : "Copy this search to the clipboard",
104
+ le && /* @__PURE__ */ w(d, {
105
+ tooltipText: he ? "Copied to clipboard" : "Copy this search to the clipboard",
117
106
  callbackFn: () => {
118
107
  e(window.location.href).then(() => {
119
108
  $(!0), setTimeout(() => {
@@ -124,52 +113,52 @@ var T = "SendToAnalysisPlatformTopLevelControlButton", E = (E) => {
124
113
  darkTheme: !0,
125
114
  icon: "clipboard"
126
115
  }),
127
- !N && /* @__PURE__ */ S(d, {
116
+ !F && /* @__PURE__ */ w(d, {
128
117
  tooltipText: "Show / Hide Visualizations",
129
- callbackFn: () => Z((e) => !e),
118
+ callbackFn: () => de((e) => !e),
130
119
  darkTheme: !0,
131
120
  icon: "chart"
132
121
  }),
133
- !M && /* @__PURE__ */ S(_, {
122
+ !P && /* @__PURE__ */ w(_, {
134
123
  darkTheme: !0,
135
- onDownloadFiles: () => pe(!0)
124
+ onDownloadFiles: () => ce(!0)
136
125
  }),
137
- !I && /* @__PURE__ */ S(d, {
126
+ !R && /* @__PURE__ */ w(d, {
138
127
  tooltipText: "Show / Hide the Advanced Query Editor",
139
- callbackFn: () => ge((e) => !e),
128
+ callbackFn: () => fe((e) => !e),
140
129
  darkTheme: !0,
141
130
  icon: "sqleditor"
142
131
  }),
143
- q && /* @__PURE__ */ S(g, {
144
- customControls: L,
145
- remount: z
132
+ q && /* @__PURE__ */ w(g, {
133
+ customControls: z,
134
+ remount: V
146
135
  }),
147
- !q && L && L.length > 0 && /* @__PURE__ */ S(x, { children: L.map((e) => /* @__PURE__ */ S(h, {
136
+ !q && z && z.length > 0 && /* @__PURE__ */ w(C, { children: z.map((e) => /* @__PURE__ */ w(h, {
148
137
  variant: "text",
149
138
  callbackData: {
150
- tableId: B,
151
- queryMetadata: G,
139
+ tableId: H,
140
+ queryMetadata: K,
152
141
  selectedRows: J,
153
142
  refresh: () => {
154
- z && z();
143
+ V && V();
155
144
  },
156
- request: U()
145
+ request: W()
157
146
  },
158
147
  control: e,
159
148
  startIcon: e.icon
160
149
  }, e.buttonText)) }),
161
- j && /* @__PURE__ */ S(ne, {
162
- headers: G?.selectColumns,
163
- isColumnSelected: X,
164
- toggleColumnSelection: xe,
150
+ N && /* @__PURE__ */ w(v, {
151
+ headers: K?.selectColumns,
152
+ isColumnSelected: Z,
153
+ toggleColumnSelection: ge,
165
154
  darkTheme: !0
166
155
  }),
167
- /* @__PURE__ */ S(m, { platformInstructionProps: { cavaticaConnectAccountURL: R } })
156
+ /* @__PURE__ */ w(m, { platformInstructionProps: { cavaticaConnectAccountURL: B } })
168
157
  ]
169
158
  })] })
170
159
  });
171
160
  };
172
161
  //#endregion
173
- export { E as default };
162
+ export { O as default };
174
163
 
175
164
  //# sourceMappingURL=TopLevelControls.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TopLevelControls.js","names":[],"sources":["../../../../src/components/SynapseTable/TopLevelControls/TopLevelControls.tsx"],"sourcesContent":["import React from 'react'\nimport { useGetEntity } from '@/synapse-queries'\nimport { SQL_EDITOR } from '@/utils/SynapseConstants'\nimport { Button, Divider, Tooltip, Typography } from '@mui/material'\nimport {\n Query,\n QueryBundleRequest,\n QueryResultBundle,\n Row,\n Table,\n} from '@sage-bionetworks/synapse-types'\nimport { useAtomValue } from 'jotai'\nimport { cloneDeep } from 'lodash-es'\nimport { ReactNode, useMemo, useState } from 'react'\nimport IconSvg from '../../IconSvg'\nimport MissingQueryResultsWarning from '../../MissingQueryResultsWarning/MissingQueryResultsWarning'\nimport { useQueryContext } from '../../QueryContext'\nimport QueryCount from '../../QueryCount/QueryCount'\nimport { useQueryVisualizationContext } from '../../QueryVisualizationWrapper'\nimport {\n isRowSelectionVisibleAtom,\n useHasSelectedRowsAtomValue,\n useSelectedRowsAtomValue,\n} from '../../QueryWrapper/TableRowSelectionState'\nimport { useGetQueryMetadata } from '../../QueryWrapper/useGetQueryMetadata'\nimport { ElementWithTooltip } from '../../widgets/ElementWithTooltip'\nimport ExportToAnalysisPlatformDialog from '../export/ExportToAnalysisPlatformDialog'\nimport { RowSelectionControls } from '../RowSelection/RowSelectionControls'\nimport { ColumnSelection, DownloadOptions } from '../table-top'\nimport {\n getNumberOfResultsToInvokeAction,\n getNumberOfResultsToInvokeActionCopy,\n} from './TopLevelControlsUtils'\nimport { copyStringToClipboard } from '@/utils/functions/StringUtils'\nimport { CustomControlButton } from '../CustomControls/CustomControlButton'\nimport { useSynapseContext } from '@/utils'\nimport { SignInRequiredModal } from '@/components/SignInRequiredModal/SignInRequiredModal'\nimport { SEND_TO_ANALYSIS_PLATFORM_SIGN_IN_MESSAGE } from '../SynapseTableUtils'\n\nconst SEND_TO_ANALYSIS_PLATFORM_BUTTON_ID =\n 'SendToAnalysisPlatformTopLevelControlButton'\n\nexport type TopLevelControlsProps = {\n name?: string\n hideDownload?: boolean\n hideVisualizationsControl?: boolean\n hideFacetFilterControl?: boolean\n hideQueryCount?: boolean\n hideSqlEditorControl?: boolean\n customControls?: CustomControl[]\n showColumnSelection?: boolean\n cavaticaConnectAccountURL?: string\n remount?: () => void\n}\n\nexport type Control = {\n key: string\n icon: string\n tooltipText: string\n}\n\nexport type CustomControlCallbackData = {\n tableId: string\n queryMetadata: Omit<QueryResultBundle, 'queryResult'> | undefined\n selectedRows: Row[] | undefined\n refresh: () => void\n request?: QueryBundleRequest\n}\n\n// note, all custom controls should check for selected rows in the event (to support row selection)\nexport type CustomControl = {\n buttonText: string\n onClick: (event: CustomControlCallbackData) => void\n classNames?: string\n icon?: ReactNode\n buttonID?: string // optionally set the ID property of the element\n title?: string // optionally set the title for the custom control\n description?: string // optionally set the description for the custom control\n}\n\nconst TopLevelControls = (props: TopLevelControlsProps): React.ReactNode => {\n const [showLoginModal, setShowLoginModal] = useState(false)\n const { isAuthenticated } = useSynapseContext()\n\n const {\n name,\n showColumnSelection = false,\n hideDownload = false,\n hideVisualizationsControl = false,\n hideFacetFilterControl = false,\n hideQueryCount = false,\n hideSqlEditorControl = true,\n customControls,\n cavaticaConnectAccountURL,\n remount,\n } = props\n\n const {\n entityId,\n versionNumber,\n getInitQueryRequest,\n getCurrentQueryRequest,\n hasResettableFilters,\n } = useQueryContext()\n const { data: entity } = useGetEntity<Table>(entityId, versionNumber)\n const { data: queryMetadata } = useGetQueryMetadata()\n const { lockedColumn } = useQueryContext()\n const isRowSelectionVisible = useAtomValue(isRowSelectionVisibleAtom)\n const selectedRows = useSelectedRowsAtomValue()\n const hasSelectedRows = useHasSelectedRowsAtomValue()\n\n const {\n setShowSearchBar,\n columnsToShowInTable,\n setColumnsToShowInTable,\n enabledExternalAnalysisPlatforms,\n setIsShowingExportToAnalysisPlatformModal,\n unitDescription,\n setShowDownloadConfirmation,\n showCopyToClipboard,\n hideSearchBarControl,\n setShowPlots,\n setShowSqlEditor,\n showFacetFilter,\n setShowFacetFilter,\n } = useQueryVisualizationContext()\n\n const showExportToAnalysisPlatformButton =\n enabledExternalAnalysisPlatforms.length > 0\n\n const [hasRecentlyCopiedToClipboard, setHasRecentlyCopiedToClipboard] =\n useState(false)\n\n /**\n * We show the total number of results that would be shown if the user removed their filters.\n * To do this, we have to create a query that captures those results.\n */\n const unfilteredResultsQuery: Query = useMemo(() => {\n const initQueryRequest = getInitQueryRequest()\n return {\n sql: initQueryRequest.query.sql,\n selectedFacets: (initQueryRequest.query.selectedFacets ?? []).filter(\n facet => facet.columnName === lockedColumn?.columnName,\n ),\n additionalFilters: (\n initQueryRequest.query.additionalFilters ?? []\n ).filter(qf =>\n 'columnName' in qf\n ? qf['columnName'] === lockedColumn?.columnName\n : true,\n ),\n }\n }, [getInitQueryRequest, lockedColumn?.columnName])\n\n /**\n * Handles the toggle of a column select, this will cause the table to\n * either show the column or hide depending on the prior state of the column\n */\n const toggleColumnSelection = (columnName: string) => {\n let columnsToShowInTableCopy = cloneDeep(columnsToShowInTable)\n if (columnsToShowInTableCopy.includes(columnName)) {\n columnsToShowInTableCopy = columnsToShowInTableCopy.filter(\n el => el !== columnName,\n )\n } else {\n columnsToShowInTableCopy.push(columnName)\n }\n setColumnsToShowInTable(columnsToShowInTableCopy)\n }\n\n const numberOfResultsToInvokeAction = getNumberOfResultsToInvokeAction(\n hasSelectedRows,\n selectedRows,\n queryMetadata?.queryCount,\n )\n const numberOfResultsToInvokeActionAsText =\n getNumberOfResultsToInvokeActionCopy(\n hasResettableFilters,\n hasSelectedRows,\n selectedRows,\n queryMetadata?.queryCount,\n unitDescription,\n )\n\n return (\n <div className={`TopLevelControls`} data-testid=\"TopLevelControls\">\n <div>\n <div className=\"TopLevelControls__querycount\">\n {name && (\n <>\n <Typography variant=\"sectionTitle\" role=\"heading\">\n {name}{' '}\n {!hideQueryCount && (\n <QueryCount query={unfilteredResultsQuery} parens={true} />\n )}\n </Typography>\n {!hideQueryCount && entity && (\n <MissingQueryResultsWarning entity={entity} />\n )}\n </>\n )}\n {!hideFacetFilterControl && (\n <Button\n variant={'text'}\n onClick={() => setShowFacetFilter(value => !value)}\n startIcon={\n <IconSvg\n icon={showFacetFilter ? 'close' : 'filter'}\n wrap={false}\n />\n }\n sx={{\n ml: 2,\n fontWeight: 400,\n fontSize: '14px',\n textDecoration: 'none !important',\n }}\n >\n {showFacetFilter ? 'Hide' : 'Show'} filters\n </Button>\n )}\n </div>\n <div className=\"TopLevelControls__actions\">\n {showExportToAnalysisPlatformButton && (\n <>\n <Tooltip\n title={\n <>\n This action will send a reference to{' '}\n {hasSelectedRows\n ? 'each selected file'\n : 'every file in the current table'}{' '}\n to a chosen external analysis platform.{' '}\n {!hasSelectedRows && showFacetFilter && (\n <>\n You can change what is sent by applying filters using\n the controls in the sidebar.\n </>\n )}\n {hasSelectedRows && (\n <>\n You can change what is sent by selecting a different set\n of files.\n </>\n )}\n </>\n }\n >\n <Button\n variant=\"text\"\n disabled={!numberOfResultsToInvokeAction}\n onClick={() => {\n return isAuthenticated\n ? setIsShowingExportToAnalysisPlatformModal(true)\n : setShowLoginModal(true)\n }}\n id={SEND_TO_ANALYSIS_PLATFORM_BUTTON_ID}\n >\n Send {numberOfResultsToInvokeActionAsText} to Analysis\n Platform\n </Button>\n </Tooltip>\n <Divider orientation=\"vertical\" variant=\"middle\" flexItem />\n </>\n )}\n {showLoginModal && (\n <SignInRequiredModal\n onHide={() => setShowLoginModal(false)}\n content={SEND_TO_ANALYSIS_PLATFORM_SIGN_IN_MESSAGE}\n />\n )}\n {!hideSearchBarControl && (\n <ElementWithTooltip\n tooltipText={'Show / Hide Search Bar'}\n callbackFn={() => setShowSearchBar(value => !value)}\n darkTheme={true}\n icon={'search'}\n />\n )}\n {showCopyToClipboard && (\n <ElementWithTooltip\n tooltipText={\n hasRecentlyCopiedToClipboard\n ? 'Copied to clipboard'\n : 'Copy this search to the clipboard'\n }\n callbackFn={() => {\n copyStringToClipboard(window.location.href).then(() => {\n setHasRecentlyCopiedToClipboard(true)\n setTimeout(() => {\n setHasRecentlyCopiedToClipboard(false)\n }, 3000)\n })\n }}\n darkTheme={true}\n icon={'clipboard'}\n />\n )}\n {!hideVisualizationsControl && (\n <ElementWithTooltip\n tooltipText={'Show / Hide Visualizations'}\n callbackFn={() => setShowPlots(value => !value)}\n darkTheme={true}\n icon={'chart'}\n />\n )}\n {!hideDownload && (\n <DownloadOptions\n darkTheme={true}\n onDownloadFiles={() => setShowDownloadConfirmation(true)}\n />\n )}\n\n {!hideSqlEditorControl && (\n <ElementWithTooltip\n tooltipText={'Show / Hide the Advanced Query Editor'}\n callbackFn={() => setShowSqlEditor(value => !value)}\n darkTheme={true}\n icon={SQL_EDITOR}\n />\n )}\n\n {isRowSelectionVisible && (\n <RowSelectionControls\n customControls={customControls}\n remount={remount}\n />\n )}\n {!isRowSelectionVisible &&\n customControls &&\n customControls.length > 0 && (\n <>\n {customControls.map(customControl => {\n return (\n <CustomControlButton\n key={customControl.buttonText}\n variant=\"text\"\n callbackData={{\n tableId: entityId!,\n queryMetadata: queryMetadata,\n selectedRows,\n refresh: () => {\n if (remount) {\n remount()\n }\n },\n request: getCurrentQueryRequest(),\n }}\n control={customControl}\n startIcon={customControl.icon}\n />\n )\n })}\n </>\n )}\n {showColumnSelection && (\n <ColumnSelection\n headers={queryMetadata?.selectColumns}\n isColumnSelected={columnsToShowInTable}\n toggleColumnSelection={toggleColumnSelection}\n darkTheme={true}\n />\n )}\n <ExportToAnalysisPlatformDialog\n platformInstructionProps={{\n cavaticaConnectAccountURL: cavaticaConnectAccountURL,\n }}\n />\n </div>\n </div>\n </div>\n )\n}\n\nexport default TopLevelControls\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuCA,IAAM,IACJ,+CAwCI,KAAoB,MAAkD;CAC1E,IAAM,CAAC,GAAgB,KAAqB,EAAS,EAAK,GACpD,EAAE,uBAAoB,EAAkB,GAExC,EACJ,SACA,yBAAsB,IACtB,kBAAe,IACf,+BAA4B,IAC5B,4BAAyB,IACzB,oBAAiB,IACjB,0BAAuB,IACvB,mBACA,8BACA,eACE,GAEE,EACJ,aACA,kBACA,wBACA,2BACA,6BACE,EAAgB,GACd,EAAE,MAAM,MAAW,GAAoB,GAAU,CAAa,GAC9D,EAAE,MAAM,MAAkB,GAAoB,GAC9C,EAAE,oBAAiB,EAAgB,GACnC,IAAwB,EAAa,CAAyB,GAC9D,IAAe,EAAyB,GACxC,IAAkB,EAA4B,GAE9C,EACJ,sBACA,yBACA,6BACA,sCACA,+CACA,qBACA,iCACA,yBACA,0BACA,iBACA,sBACA,oBACA,2BACE,EAA6B,GAE3B,KACJ,GAAiC,SAAS,GAEtC,CAAC,IAA8B,KACnC,EAAS,EAAK,GAMV,KAAgC,SAAc;EAClD,IAAM,IAAmB,EAAoB;EAC7C,OAAO;GACL,KAAK,EAAiB,MAAM;GAC5B,iBAAiB,EAAiB,MAAM,kBAAkB,CAAC,GAAG,QAC5D,MAAS,EAAM,eAAe,GAAc,UAC9C;GACA,oBACE,EAAiB,MAAM,qBAAqB,CAAC,GAC7C,QAAO,MACP,gBAAgB,IACZ,EAAG,eAAkB,GAAc,aACnC,EACN;EACF;CACF,GAAG,CAAC,GAAqB,GAAc,UAAU,CAAC,GAM5C,MAAyB,MAAuB;EACpD,IAAI,IAA2B,GAAU,CAAoB;EAQ7D,AAPI,EAAyB,SAAS,CAAU,IAC9C,IAA2B,EAAyB,QAClD,MAAM,MAAO,CACf,IAEA,EAAyB,KAAK,CAAU,GAE1C,GAAwB,CAAwB;CAClD,GAEM,KAAgC,EACpC,GACA,GACA,GAAe,UACjB,GACM,KACJ,EACE,IACA,GACA,GACA,GAAe,YACf,EACF;CAEF,OACE,kBAAC,OAAD;EAAK,WAAW;EAAoB,eAAY;YAC9C,kBAAC,OAAD,EAAA,UAAA,CACE,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,KACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;IAAY,SAAQ;IAAe,MAAK;cAAxC;KACG;KAAM;KACN,CAAC,KACA,kBAAC,GAAD;MAAY,OAAO;MAAwB,QAAQ;KAAO,CAAA;IAElD;OACX,CAAC,KAAkB,KAClB,kBAAC,GAAD,EAAoC,UAAS,CAAA,CAE/C,EAAA,CAAA,GAEH,CAAC,KACA,kBAAC,GAAD;IACE,SAAS;IACT,eAAe,IAAmB,MAAS,CAAC,CAAK;IACjD,WACE,kBAAC,GAAD;KACE,MAAM,IAAkB,UAAU;KAClC,MAAM;IACP,CAAA;IAEH,IAAI;KACF,IAAI;KACJ,YAAY;KACZ,UAAU;KACV,gBAAgB;IAClB;cAdF,CAgBG,IAAkB,SAAS,QAAO,UAC7B;KAEP;MACL,kBAAC,OAAD;GAAK,WAAU;aAAf;IACG,MACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,IAAD;KACE,OACE,kBAAA,GAAA,EAAA,UAAA;MAAE;MACqC;MACpC,IACG,uBACA;MAAmC;MAAI;MACH;MACvC,CAAC,KAAmB,KACnB,kBAAA,GAAA,EAAA,UAAE,qFAGA,CAAA;MAEH,KACC,kBAAA,GAAA,EAAA,UAAE,qEAGA,CAAA;KAEJ,EAAA,CAAA;eAGJ,kBAAC,GAAD;MACE,SAAQ;MACR,UAAU,CAAC;MACX,eACS,IACH,GAA0C,EAAI,IAC9C,EAAkB,EAAI;MAE5B,IAAI;gBARN;OASC;OACO;OAAoC;MAEpC;;IACD,CAAA,GACT,kBAAC,IAAD;KAAS,aAAY;KAAW,SAAQ;KAAS,UAAA;IAAU,CAAA,CAC3D,EAAA,CAAA;IAEH,KACC,kBAAC,GAAD;KACE,cAAc,EAAkB,EAAK;KACrC,SAAA;IACD,CAAA;IAEF,CAAC,MACA,kBAAC,GAAD;KACE,aAAa;KACb,kBAAkB,IAAiB,MAAS,CAAC,CAAK;KAClD,WAAW;KACX,MAAM;IACP,CAAA;IAEF,MACC,kBAAC,GAAD;KACE,aACE,KACI,wBACA;KAEN,kBAAkB;MAChB,EAAsB,OAAO,SAAS,IAAI,EAAE,WAAW;OAErD,AADA,EAAgC,EAAI,GACpC,iBAAiB;QACf,EAAgC,EAAK;OACvC,GAAG,GAAI;MACT,CAAC;KACH;KACA,WAAW;KACX,MAAM;IACP,CAAA;IAEF,CAAC,KACA,kBAAC,GAAD;KACE,aAAa;KACb,kBAAkB,GAAa,MAAS,CAAC,CAAK;KAC9C,WAAW;KACX,MAAM;IACP,CAAA;IAEF,CAAC,KACA,kBAAC,GAAD;KACE,WAAW;KACX,uBAAuB,GAA4B,EAAI;IACxD,CAAA;IAGF,CAAC,KACA,kBAAC,GAAD;KACE,aAAa;KACb,kBAAkB,IAAiB,MAAS,CAAC,CAAK;KAClD,WAAW;KACX,MAAA;IACD,CAAA;IAGF,KACC,kBAAC,GAAD;KACkB;KACP;IACV,CAAA;IAEF,CAAC,KACA,KACA,EAAe,SAAS,KACtB,kBAAA,GAAA,EAAA,UACG,EAAe,KAAI,MAEhB,kBAAC,GAAD;KAEE,SAAQ;KACR,cAAc;MACZ,SAAS;MACM;MACf;MACA,eAAe;OACb,AAAI,KACF,EAAQ;MAEZ;MACA,SAAS,EAAuB;KAClC;KACA,SAAS;KACT,WAAW,EAAc;IAC1B,GAfM,EAAc,UAepB,CAEJ,EACD,CAAA;IAEL,KACC,kBAAC,IAAD;KACE,SAAS,GAAe;KACxB,kBAAkB;KACK;KACvB,WAAW;IACZ,CAAA;IAEH,kBAAC,GAAD,EACE,0BAA0B,EACG,6BAC7B,EACD,CAAA;GACE;IACF,EAAA,CAAA;CACF,CAAA;AAET"}
1
+ {"version":3,"file":"TopLevelControls.js","names":[],"sources":["../../../../src/components/SynapseTable/TopLevelControls/TopLevelControls.tsx"],"sourcesContent":["import React from 'react'\nimport { useGetEntity } from '@/synapse-queries'\nimport { SQL_EDITOR } from '@/utils/SynapseConstants'\nimport { Button, Divider, Tooltip, Typography } from '@mui/material'\nimport {\n QueryBundleRequest,\n QueryResultBundle,\n Row,\n Table,\n} from '@sage-bionetworks/synapse-types'\nimport { useAtomValue } from 'jotai'\nimport { cloneDeep } from 'lodash-es'\nimport { ReactNode, useState } from 'react'\nimport IconSvg from '../../IconSvg'\nimport MissingQueryResultsWarning from '../../MissingQueryResultsWarning/MissingQueryResultsWarning'\nimport { useQueryContext } from '../../QueryContext'\nimport { useQueryVisualizationContext } from '../../QueryVisualizationWrapper'\nimport {\n isRowSelectionVisibleAtom,\n useHasSelectedRowsAtomValue,\n useSelectedRowsAtomValue,\n} from '../../QueryWrapper/TableRowSelectionState'\nimport { useGetQueryMetadata } from '../../QueryWrapper/useGetQueryMetadata'\nimport { ElementWithTooltip } from '../../widgets/ElementWithTooltip'\nimport ExportToAnalysisPlatformDialog from '../export/ExportToAnalysisPlatformDialog'\nimport { RowSelectionControls } from '../RowSelection/RowSelectionControls'\nimport { ColumnSelection, DownloadOptions } from '../table-top'\nimport {\n getNumberOfResultsToInvokeAction,\n getNumberOfResultsToInvokeActionCopy,\n} from './TopLevelControlsUtils'\nimport { copyStringToClipboard } from '@/utils/functions/StringUtils'\nimport { CustomControlButton } from '../CustomControls/CustomControlButton'\nimport { useSynapseContext } from '@/utils'\nimport { SignInRequiredModal } from '@/components/SignInRequiredModal/SignInRequiredModal'\nimport { SEND_TO_ANALYSIS_PLATFORM_SIGN_IN_MESSAGE } from '../SynapseTableUtils'\n\nconst SEND_TO_ANALYSIS_PLATFORM_BUTTON_ID =\n 'SendToAnalysisPlatformTopLevelControlButton'\n\nexport type TopLevelControlsProps = {\n name?: string\n hideDownload?: boolean\n hideVisualizationsControl?: boolean\n hideFacetFilterControl?: boolean\n hideQueryCount?: boolean\n hideSqlEditorControl?: boolean\n customControls?: CustomControl[]\n showColumnSelection?: boolean\n cavaticaConnectAccountURL?: string\n remount?: () => void\n}\n\nexport type Control = {\n key: string\n icon: string\n tooltipText: string\n}\n\nexport type CustomControlCallbackData = {\n tableId: string\n queryMetadata: Omit<QueryResultBundle, 'queryResult'> | undefined\n selectedRows: Row[] | undefined\n refresh: () => void\n request?: QueryBundleRequest\n}\n\n// note, all custom controls should check for selected rows in the event (to support row selection)\nexport type CustomControl = {\n buttonText: string\n onClick: (event: CustomControlCallbackData) => void\n classNames?: string\n icon?: ReactNode\n buttonID?: string // optionally set the ID property of the element\n title?: string // optionally set the title for the custom control\n description?: string // optionally set the description for the custom control\n}\n\nconst TopLevelControls = (props: TopLevelControlsProps): React.ReactNode => {\n const [showLoginModal, setShowLoginModal] = useState(false)\n const { isAuthenticated } = useSynapseContext()\n\n const {\n name,\n showColumnSelection = false,\n hideDownload = false,\n hideVisualizationsControl = false,\n hideFacetFilterControl = false,\n hideQueryCount = false,\n hideSqlEditorControl = true,\n customControls,\n cavaticaConnectAccountURL,\n remount,\n } = props\n\n const {\n entityId,\n versionNumber,\n getCurrentQueryRequest,\n hasResettableFilters,\n } = useQueryContext()\n const { data: entity } = useGetEntity<Table>(entityId, versionNumber)\n const { data: queryMetadata } = useGetQueryMetadata()\n const isRowSelectionVisible = useAtomValue(isRowSelectionVisibleAtom)\n const selectedRows = useSelectedRowsAtomValue()\n const hasSelectedRows = useHasSelectedRowsAtomValue()\n\n const {\n setShowSearchBar,\n columnsToShowInTable,\n setColumnsToShowInTable,\n enabledExternalAnalysisPlatforms,\n setIsShowingExportToAnalysisPlatformModal,\n unitDescription,\n setShowDownloadConfirmation,\n showCopyToClipboard,\n hideSearchBarControl,\n setShowPlots,\n setShowSqlEditor,\n showFacetFilter,\n setShowFacetFilter,\n } = useQueryVisualizationContext()\n\n const showExportToAnalysisPlatformButton =\n enabledExternalAnalysisPlatforms.length > 0\n\n const [hasRecentlyCopiedToClipboard, setHasRecentlyCopiedToClipboard] =\n useState(false)\n\n /**\n * Handles the toggle of a column select, this will cause the table to\n * either show the column or hide depending on the prior state of the column\n */\n const toggleColumnSelection = (columnName: string) => {\n let columnsToShowInTableCopy = cloneDeep(columnsToShowInTable)\n if (columnsToShowInTableCopy.includes(columnName)) {\n columnsToShowInTableCopy = columnsToShowInTableCopy.filter(\n el => el !== columnName,\n )\n } else {\n columnsToShowInTableCopy.push(columnName)\n }\n setColumnsToShowInTable(columnsToShowInTableCopy)\n }\n\n const numberOfResultsToInvokeAction = getNumberOfResultsToInvokeAction(\n hasSelectedRows,\n selectedRows,\n queryMetadata?.queryCount,\n )\n const numberOfResultsToInvokeActionAsText =\n getNumberOfResultsToInvokeActionCopy(\n hasResettableFilters,\n hasSelectedRows,\n selectedRows,\n queryMetadata?.queryCount,\n unitDescription,\n )\n\n const queryCountDisplay =\n !hideQueryCount && queryMetadata?.queryCount !== undefined\n ? `(${queryMetadata.queryCount.toLocaleString()})`\n : null\n\n return (\n <div className={`TopLevelControls`} data-testid=\"TopLevelControls\">\n <div>\n <div className=\"TopLevelControls__querycount\">\n {name && (\n <>\n <Typography variant=\"sectionTitle\" role=\"heading\">\n {name} {queryCountDisplay}\n </Typography>\n {!hideQueryCount && entity && (\n <MissingQueryResultsWarning entity={entity} />\n )}\n </>\n )}\n {!hideFacetFilterControl && (\n <Button\n variant={'text'}\n onClick={() => setShowFacetFilter(value => !value)}\n startIcon={\n <IconSvg\n icon={showFacetFilter ? 'close' : 'filter'}\n wrap={false}\n />\n }\n sx={{\n ml: 2,\n fontWeight: 400,\n fontSize: '14px',\n textDecoration: 'none !important',\n }}\n >\n {showFacetFilter ? 'Hide' : 'Show'} filters\n </Button>\n )}\n </div>\n <div className=\"TopLevelControls__actions\">\n {showExportToAnalysisPlatformButton && (\n <>\n <Tooltip\n title={\n <>\n This action will send a reference to{' '}\n {hasSelectedRows\n ? 'each selected file'\n : 'every file in the current table'}{' '}\n to a chosen external analysis platform.{' '}\n {!hasSelectedRows && showFacetFilter && (\n <>\n You can change what is sent by applying filters using\n the controls in the sidebar.\n </>\n )}\n {hasSelectedRows && (\n <>\n You can change what is sent by selecting a different set\n of files.\n </>\n )}\n </>\n }\n >\n <Button\n variant=\"text\"\n disabled={!numberOfResultsToInvokeAction}\n onClick={() => {\n return isAuthenticated\n ? setIsShowingExportToAnalysisPlatformModal(true)\n : setShowLoginModal(true)\n }}\n id={SEND_TO_ANALYSIS_PLATFORM_BUTTON_ID}\n >\n Send {numberOfResultsToInvokeActionAsText} to Analysis\n Platform\n </Button>\n </Tooltip>\n <Divider orientation=\"vertical\" variant=\"middle\" flexItem />\n </>\n )}\n {showLoginModal && (\n <SignInRequiredModal\n onHide={() => setShowLoginModal(false)}\n content={SEND_TO_ANALYSIS_PLATFORM_SIGN_IN_MESSAGE}\n />\n )}\n {!hideSearchBarControl && (\n <ElementWithTooltip\n tooltipText={'Show / Hide Search Bar'}\n callbackFn={() => setShowSearchBar(value => !value)}\n darkTheme={true}\n icon={'search'}\n />\n )}\n {showCopyToClipboard && (\n <ElementWithTooltip\n tooltipText={\n hasRecentlyCopiedToClipboard\n ? 'Copied to clipboard'\n : 'Copy this search to the clipboard'\n }\n callbackFn={() => {\n copyStringToClipboard(window.location.href).then(() => {\n setHasRecentlyCopiedToClipboard(true)\n setTimeout(() => {\n setHasRecentlyCopiedToClipboard(false)\n }, 3000)\n })\n }}\n darkTheme={true}\n icon={'clipboard'}\n />\n )}\n {!hideVisualizationsControl && (\n <ElementWithTooltip\n tooltipText={'Show / Hide Visualizations'}\n callbackFn={() => setShowPlots(value => !value)}\n darkTheme={true}\n icon={'chart'}\n />\n )}\n {!hideDownload && (\n <DownloadOptions\n darkTheme={true}\n onDownloadFiles={() => setShowDownloadConfirmation(true)}\n />\n )}\n\n {!hideSqlEditorControl && (\n <ElementWithTooltip\n tooltipText={'Show / Hide the Advanced Query Editor'}\n callbackFn={() => setShowSqlEditor(value => !value)}\n darkTheme={true}\n icon={SQL_EDITOR}\n />\n )}\n\n {isRowSelectionVisible && (\n <RowSelectionControls\n customControls={customControls}\n remount={remount}\n />\n )}\n {!isRowSelectionVisible &&\n customControls &&\n customControls.length > 0 && (\n <>\n {customControls.map(customControl => {\n return (\n <CustomControlButton\n key={customControl.buttonText}\n variant=\"text\"\n callbackData={{\n tableId: entityId!,\n queryMetadata: queryMetadata,\n selectedRows,\n refresh: () => {\n if (remount) {\n remount()\n }\n },\n request: getCurrentQueryRequest(),\n }}\n control={customControl}\n startIcon={customControl.icon}\n />\n )\n })}\n </>\n )}\n {showColumnSelection && (\n <ColumnSelection\n headers={queryMetadata?.selectColumns}\n isColumnSelected={columnsToShowInTable}\n toggleColumnSelection={toggleColumnSelection}\n darkTheme={true}\n />\n )}\n <ExportToAnalysisPlatformDialog\n platformInstructionProps={{\n cavaticaConnectAccountURL: cavaticaConnectAccountURL,\n }}\n />\n </div>\n </div>\n </div>\n )\n}\n\nexport default TopLevelControls\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ColumnModelForm.d.ts","sourceRoot":"","sources":["../../../src/components/TableColumnSchemaEditor/ColumnModelForm.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAC7D,OAAO,EACL,WAAW,EAKZ,MAAM,iCAAiC,CAAA;AAKxC,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAA;AAsB9B,KAAK,oBAAoB,GAAG;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,gBAAgB,EAAE,MAAM,CAAA;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B,eAAe,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;IACpC,sBAAsB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3C,mBAAmB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;CACzC,CAAA;AAoED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,KAAK,EAAE,oBAAoB,2CAiiBlE"}
1
+ {"version":3,"file":"ColumnModelForm.d.ts","sourceRoot":"","sources":["../../../src/components/TableColumnSchemaEditor/ColumnModelForm.tsx"],"names":[],"mappings":"AAcA,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAC7D,OAAO,EACL,WAAW,EAKZ,MAAM,iCAAiC,CAAA;AAKxC,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,CAAA;AAwB9B,KAAK,oBAAoB,GAAG;IAC1B,UAAU,EAAE,UAAU,CAAA;IACtB,gBAAgB,EAAE,MAAM,CAAA;IACxB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAE3B,eAAe,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAElB,gBAAgB,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,CAAA;IACpC,sBAAsB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;IAC3C,mBAAmB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;CACzC,CAAA;AAoED,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,KAAK,EAAE,oBAAoB,2CA0iBlE"}