@gen3/core 0.10.80 → 0.10.81

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 (85) hide show
  1. package/dist/cjs/index.js +677 -444
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/dts/constants.d.ts.map +1 -1
  4. package/dist/dts/dataAccess.d.ts.map +1 -1
  5. package/dist/dts/features/cohort/cohortSlice.d.ts.map +1 -1
  6. package/dist/dts/features/cohort/filterCombineModeSlice.d.ts +12 -0
  7. package/dist/dts/features/cohort/filterCombineModeSlice.d.ts.map +1 -0
  8. package/dist/dts/features/cohort/filterExpandSlice.d.ts +15 -0
  9. package/dist/dts/features/cohort/filterExpandSlice.d.ts.map +1 -0
  10. package/dist/dts/features/cohort/index.d.ts +6 -2
  11. package/dist/dts/features/cohort/index.d.ts.map +1 -1
  12. package/dist/dts/features/cohort/reducers.d.ts +20 -0
  13. package/dist/dts/features/cohort/reducers.d.ts.map +1 -0
  14. package/dist/dts/features/cohort/sharedFiltersSlice.d.ts +17 -0
  15. package/dist/dts/features/cohort/sharedFiltersSlice.d.ts.map +1 -0
  16. package/dist/dts/features/cohort/types.d.ts +1 -0
  17. package/dist/dts/features/cohort/types.d.ts.map +1 -1
  18. package/dist/dts/features/dataLibrary/dataLibraryIndexDB.d.ts.map +1 -1
  19. package/dist/dts/features/dataLibrary/dataLibrarySelectionSlice.d.ts.map +1 -1
  20. package/dist/dts/features/dataLibrary/types.d.ts.map +1 -1
  21. package/dist/dts/features/dataLibrary/useDataLibrary.d.ts.map +1 -1
  22. package/dist/dts/features/dataLibrary/utils.d.ts.map +1 -1
  23. package/dist/dts/features/drsResolver/drsHostnameSlice.d.ts.map +1 -1
  24. package/dist/dts/features/drsResolver/resolvers/cachedDRSResolver.d.ts.map +1 -1
  25. package/dist/dts/features/drsResolver/resolvers/dataGUIDSDotOrg.d.ts.map +1 -1
  26. package/dist/dts/features/drsResolver/utils.d.ts.map +1 -1
  27. package/dist/dts/features/fence/credentialsApi.d.ts.map +1 -1
  28. package/dist/dts/features/fence/fenceApi.d.ts.map +1 -1
  29. package/dist/dts/features/fence/index.d.ts +2 -2
  30. package/dist/dts/features/fence/index.d.ts.map +1 -1
  31. package/dist/dts/features/fence/utils.d.ts +1 -0
  32. package/dist/dts/features/fence/utils.d.ts.map +1 -1
  33. package/dist/dts/features/filters/filters.d.ts +2 -0
  34. package/dist/dts/features/filters/filters.d.ts.map +1 -1
  35. package/dist/dts/features/filters/index.d.ts +2 -2
  36. package/dist/dts/features/filters/index.d.ts.map +1 -1
  37. package/dist/dts/features/filters/types.d.ts +4 -0
  38. package/dist/dts/features/filters/types.d.ts.map +1 -1
  39. package/dist/dts/features/filters/utils.d.ts.map +1 -1
  40. package/dist/dts/features/gen3/index.d.ts.map +1 -1
  41. package/dist/dts/features/gen3Apps/Gen3App.d.ts.map +1 -1
  42. package/dist/dts/features/gen3Apps/Gen3AppRTKQ.d.ts.map +1 -1
  43. package/dist/dts/features/gen3Apps/gen3AppRegistry.d.ts.map +1 -1
  44. package/dist/dts/features/gen3Apps/gen3AppsSlice.d.ts.map +1 -1
  45. package/dist/dts/features/guppy/guppySlice.d.ts +373 -0
  46. package/dist/dts/features/guppy/guppySlice.d.ts.map +1 -1
  47. package/dist/dts/features/guppy/index.d.ts +2 -2
  48. package/dist/dts/features/guppy/index.d.ts.map +1 -1
  49. package/dist/dts/features/guppy/tests/grouping.unit.test.d.ts +2 -0
  50. package/dist/dts/features/guppy/tests/grouping.unit.test.d.ts.map +1 -0
  51. package/dist/dts/features/guppy/types.d.ts +6 -0
  52. package/dist/dts/features/guppy/types.d.ts.map +1 -1
  53. package/dist/dts/features/guppy/utils.d.ts +2 -1
  54. package/dist/dts/features/guppy/utils.d.ts.map +1 -1
  55. package/dist/dts/features/modals/modalsSlice.d.ts.map +1 -1
  56. package/dist/dts/features/submission/authMappingUtils.d.ts.map +1 -1
  57. package/dist/dts/features/user/hooks.d.ts.map +1 -1
  58. package/dist/dts/features/user/userSlice.d.ts.map +1 -1
  59. package/dist/dts/features/user/userSliceRTK.d.ts +30 -3
  60. package/dist/dts/features/user/userSliceRTK.d.ts.map +1 -1
  61. package/dist/dts/features/user/utils.d.ts.map +1 -1
  62. package/dist/dts/features/workspace/utils.d.ts.map +1 -1
  63. package/dist/dts/features/workspace/workspaceSlice.d.ts.map +1 -1
  64. package/dist/dts/hooks.d.ts +20 -2
  65. package/dist/dts/hooks.d.ts.map +1 -1
  66. package/dist/dts/reducers.d.ts +29 -2
  67. package/dist/dts/reducers.d.ts.map +1 -1
  68. package/dist/dts/store.d.ts +40 -4
  69. package/dist/dts/store.d.ts.map +1 -1
  70. package/dist/dts/types/index.d.ts.map +1 -1
  71. package/dist/dts/utils/extractvalues.d.ts.map +1 -1
  72. package/dist/dts/utils/fetch.d.ts +21 -2
  73. package/dist/dts/utils/fetch.d.ts.map +1 -1
  74. package/dist/dts/utils/index.d.ts +2 -2
  75. package/dist/dts/utils/index.d.ts.map +1 -1
  76. package/dist/dts/utils/time.d.ts.map +1 -1
  77. package/dist/dts/utils/ts-utils.d.ts.map +1 -1
  78. package/dist/dts/utils/url.d.ts.map +1 -1
  79. package/dist/esm/index.js +660 -444
  80. package/dist/esm/index.js.map +1 -1
  81. package/dist/index.d.ts +5200 -4656
  82. package/package.json +2 -3
  83. package/LICENSE +0 -201
  84. package/dist/dts/features/cohort/cohortBuilderConfigSlice.d.ts +0 -1
  85. package/dist/dts/features/cohort/cohortBuilderConfigSlice.d.ts.map +0 -1
package/dist/cjs/index.js CHANGED
@@ -46,7 +46,7 @@ const GEN3_DOMAIN = process.env.NEXT_PUBLIC_GEN3_DOMAIN || '';
46
46
  */ const GEN3_GUPPY_API = process.env.NEXT_PUBLIC_GEN3_GUPPY_API || `${GEN3_API}/guppy`;
47
47
  const GEN3_MDS_API = process.env.NEXT_PUBLIC_GEN3_MDS_API || `${GEN3_API}/mds`;
48
48
  const GEN3_DOWNLOADS_ENDPOINT = process.env.NEXT_PUBLIC_GEN3_DOWNLOADS_ENDPOINT || 'downloads';
49
- const GEN3_FENCE_API = process.env.NEXT_PUBLIC_GEN3_FENCE_API || GEN3_API;
49
+ const GEN3_FENCE_API = process.env.NEXT_PUBLIC_GEN3_FENCE_API || `${GEN3_API}/user`;
50
50
  const GEN3_AI_SEARCH_API = process.env.NEXT_PUBLIC_GEN3_AI_SEARCH_API || `${GEN3_API}/ai-search`;
51
51
  const GEN3_AUTHZ_API = process.env.NEXT_PUBLIC_GEN3_AUTHZ_API || `${GEN3_API}/authz`;
52
52
  const GEN3_REDIRECT_URL = process.env.NEXT_PUBLIC_GEN3_REDIRECT_URL || GEN3_API;
@@ -67,6 +67,13 @@ const FILE_DELIMITERS = {
67
67
  csv: ','
68
68
  };
69
69
 
70
+ const isFetchError = (obj)=>{
71
+ if (typeof obj !== 'object' || obj === null) {
72
+ return false;
73
+ }
74
+ const { url, status, statusText, text } = obj;
75
+ return typeof url === 'string' && typeof status === 'number' && typeof statusText === 'string' && typeof text === 'string';
76
+ };
70
77
  /**
71
78
  * Template for fence error response dict
72
79
  * @returns: An error dict response from a RESTFUL API request
@@ -143,7 +150,7 @@ const userAuthApi = react.createApi({
143
150
  endpoints: (builder)=>({
144
151
  fetchUserDetails: builder.query({
145
152
  query: ()=>({
146
- endpoint: '/user/user'
153
+ endpoint: '/user'
147
154
  }),
148
155
  transformResponse (response) {
149
156
  return {
@@ -154,12 +161,33 @@ const userAuthApi = react.createApi({
154
161
  }
155
162
  }),
156
163
  getCSRF: builder.query({
157
- query: ()=>({
158
- endpoint: '/_status'
159
- }),
160
- transformResponse: (response)=>{
164
+ queryFn: async ()=>{
165
+ const headers = {
166
+ Accept: 'application/json',
167
+ 'Content-Type': 'application/json'
168
+ };
169
+ try {
170
+ const res = await fetch(`${GEN3_API}/_status`, {
171
+ headers: headers
172
+ });
173
+ if (res.ok) {
174
+ const jsonData = await res.json();
175
+ const token = jsonData?.data?.csrf ?? '';
176
+ return {
177
+ data: {
178
+ csrfToken: token
179
+ }
180
+ };
181
+ }
182
+ } catch (error) {
183
+ if (error instanceof Error) {
184
+ return {
185
+ error: error
186
+ };
187
+ }
188
+ }
161
189
  return {
162
- csrfToken: response?.data?.csrf ?? ''
190
+ error: 'Unknown Error'
163
191
  };
164
192
  }
165
193
  })
@@ -227,13 +255,13 @@ const gen3ServicesReducerMiddleware = gen3Api.middleware;
227
255
  */ const loginProvidersApi = gen3Api.injectEndpoints({
228
256
  endpoints: (builder)=>({
229
257
  getLoginProviders: builder.query({
230
- query: ()=>`${GEN3_FENCE_API}/user/login`
258
+ query: ()=>`${GEN3_FENCE_API}/login`
231
259
  }),
232
260
  getDownload: builder.query({
233
- query: (guid)=>`${GEN3_FENCE_API}/user/data/download/${guid}`
261
+ query: (guid)=>`${GEN3_FENCE_API}/data/download/${guid}`
234
262
  }),
235
263
  getPresignedUrl: builder.query({
236
- query: ({ guid, what })=>`${GEN3_FENCE_API}/user/data/${what}/${guid}`
264
+ query: ({ guid, what })=>`${GEN3_FENCE_API}/data/${what}/${guid}`
237
265
  })
238
266
  })
239
267
  });
@@ -241,7 +269,7 @@ const { useGetLoginProvidersQuery, useGetDownloadQuery, useLazyGetDownloadQuery,
241
269
  /**
242
270
  * Logout from fence
243
271
  */ const logoutFence = async (redirect = '/')=>await fetchFence({
244
- endpoint: `${GEN3_FENCE_API}/user/logout?next=${GEN3_REDIRECT_URL}${redirect}`,
272
+ endpoint: `${GEN3_FENCE_API}/logout?next=${GEN3_REDIRECT_URL}${redirect}`,
245
273
  method: 'GET'
246
274
  });
247
275
 
@@ -262,7 +290,7 @@ const credentialsWithTags$1 = gen3Api.enhanceEndpoints({
262
290
  */ const credentialsApi = credentialsWithTags$1.injectEndpoints({
263
291
  endpoints: (builder)=>({
264
292
  getCredentials: builder.query({
265
- query: ()=>`${GEN3_FENCE_API}/user/credentials/api`,
293
+ query: ()=>`${GEN3_FENCE_API}/credentials/api`,
266
294
  transformResponse: (response)=>response['jtis'],
267
295
  // "jtis", which is an array of API keys
268
296
  // no need to transform the response, since the API returns the correct format
@@ -272,7 +300,7 @@ const credentialsWithTags$1 = gen3Api.enhanceEndpoints({
272
300
  }),
273
301
  addNewCredential: builder.mutation({
274
302
  query: (csrfToken)=>({
275
- url: `${GEN3_FENCE_API}/user/credentials/api`,
303
+ url: `${GEN3_FENCE_API}/credentials/api`,
276
304
  method: 'POST',
277
305
  headers: {
278
306
  'Content-Type': 'application/json',
@@ -291,7 +319,7 @@ const credentialsWithTags$1 = gen3Api.enhanceEndpoints({
291
319
  }),
292
320
  removeCredential: builder.mutation({
293
321
  query: ({ csrfToken, id })=>({
294
- url: `${GEN3_FENCE_API}/user/credentials/api/${id}`,
322
+ url: `${GEN3_FENCE_API}/credentials/api/${id}`,
295
323
  method: 'DELETE',
296
324
  headers: {
297
325
  'Content-Type': 'application/json',
@@ -306,7 +334,7 @@ const credentialsWithTags$1 = gen3Api.enhanceEndpoints({
306
334
  }),
307
335
  authorizeFromCredentials: builder.mutation({
308
336
  query: (params)=>({
309
- url: `${GEN3_FENCE_API}/user/credentials/api/access_token`,
337
+ url: `${GEN3_FENCE_API}/credentials/api/access_token`,
310
338
  method: 'POST',
311
339
  headers: {
312
340
  'Content-Type': 'application/json'
@@ -404,7 +432,7 @@ const createUseCoreDataHook = (fetchDataActionCreator, dataSelector)=>{
404
432
  accessToken = cookiesNext.getCookie('credentials_token');
405
433
  }
406
434
  return await fetchFence({
407
- endpoint: '/user/user',
435
+ endpoint: '/user',
408
436
  method: 'GET',
409
437
  headers: {
410
438
  Accept: 'application/json',
@@ -421,7 +449,7 @@ const createUseCoreDataHook = (fetchDataActionCreator, dataSelector)=>{
421
449
  });
422
450
  const isAuthenticated = (loginStatus)=>loginStatus === 'authenticated';
423
451
  const isPending = (loginStatus)=>loginStatus === 'pending';
424
- const initialState$5 = {
452
+ const initialState$8 = {
425
453
  status: 'uninitialized',
426
454
  loginStatus: 'unauthenticated',
427
455
  error: undefined
@@ -432,9 +460,9 @@ const initialState$5 = {
432
460
  * @returns: status messages wrapped around fetchUserState response dict
433
461
  */ const slice$4 = toolkit.createSlice({
434
462
  name: 'fence/user',
435
- initialState: initialState$5,
463
+ initialState: initialState$8,
436
464
  reducers: {
437
- resetUserState: ()=>initialState$5
465
+ resetUserState: ()=>initialState$8
438
466
  },
439
467
  extraReducers: (builder)=>{
440
468
  builder.addCase(fetchUserState.fulfilled, (_, action)=>{
@@ -604,12 +632,12 @@ const lookupGen3App = (id)=>{
604
632
  return REGISTRY[id];
605
633
  };
606
634
 
607
- const initialState$4 = {
635
+ const initialState$7 = {
608
636
  gen3Apps: {}
609
637
  };
610
638
  const slice$3 = toolkit.createSlice({
611
639
  name: 'gen3Apps',
612
- initialState: initialState$4,
640
+ initialState: initialState$7,
613
641
  reducers: {
614
642
  addGen3AppMetadata: (state, action)=>{
615
643
  const { name, requiredEntityTypes } = action.payload;
@@ -628,11 +656,11 @@ const { addGen3AppMetadata } = slice$3.actions;
628
656
  const selectGen3AppMetadataByName = (state, appName)=>state.gen3Apps.gen3Apps[appName];
629
657
  const selectGen3AppByName = (appName)=>lookupGen3App(appName); // TODO: memoize this selector
630
658
 
631
- const initialState$3 = {};
659
+ const initialState$6 = {};
632
660
  // TODO: document what this does
633
661
  const slice$2 = toolkit.createSlice({
634
662
  name: 'drsResolver',
635
- initialState: initialState$3,
663
+ initialState: initialState$6,
636
664
  reducers: {
637
665
  setDRSHostnames: (_state, action)=>{
638
666
  return action.payload;
@@ -654,13 +682,13 @@ const { setDRSHostnames } = slice$2.actions;
654
682
  Modals["GeneralErrorModal"] = "GeneralErrorModal";
655
683
  return Modals;
656
684
  }({});
657
- const initialState$2 = {
685
+ const initialState$5 = {
658
686
  currentModal: null
659
687
  };
660
688
  //Creates a modal slice for tracking showModal and hideModal state.
661
689
  const slice$1 = toolkit.createSlice({
662
690
  name: 'modals',
663
- initialState: initialState$2,
691
+ initialState: initialState$5,
664
692
  reducers: {
665
693
  showModal: (state, action)=>{
666
694
  state.currentModal = action.payload.modal;
@@ -678,141 +706,6 @@ const { showModal, hideModal } = slice$1.actions;
678
706
  const selectCurrentModal = (state)=>state.modals.currentModal;
679
707
  const selectCurrentMessage = (state)=>state.modals.message;
680
708
 
681
- const EmptyCohort = {
682
- id: 'default',
683
- name: 'Filters',
684
- filters: {},
685
- modified_datetime: new Date().toISOString()
686
- };
687
- const initialCohortState = {
688
- cohort: {
689
- ...EmptyCohort
690
- }
691
- };
692
- // TODO: start using this adapter
693
- /*
694
- const cohortsAdapter = createEntityAdapter<Cohort>({
695
- sortComparer: (a, b) => {
696
- if (a.modified_datetime <= b.modified_datetime) return 1;
697
- else return -1;
698
- },
699
- });
700
- */ /**
701
- * Redux slice for cohort filters
702
- */ const cohortSlice = toolkit.createSlice({
703
- name: 'cohort',
704
- initialState: initialCohortState,
705
- reducers: {
706
- // adds a filter to the cohort filter set at the given index
707
- updateCohortFilter: (state, action)=>{
708
- const { index, field, filter } = action.payload;
709
- return {
710
- cohort: {
711
- ...state.cohort,
712
- filters: {
713
- ...state.cohort.filters,
714
- [index]: {
715
- mode: state.cohort.filters?.[index]?.mode ?? 'and',
716
- root: {
717
- ...state.cohort.filters?.[index]?.root ?? {},
718
- [field]: filter
719
- }
720
- }
721
- }
722
- }
723
- };
724
- },
725
- setCohortFilter: (state, action)=>{
726
- const { index, filters } = action.payload;
727
- return {
728
- cohort: {
729
- ...state.cohort,
730
- filters: {
731
- ...state.cohort.filters,
732
- [index]: filters
733
- }
734
- }
735
- };
736
- },
737
- setCohortIndexFilters: (state, action)=>{
738
- return {
739
- cohort: {
740
- ...state.cohort,
741
- filters: {
742
- ...action.payload.filters
743
- }
744
- }
745
- };
746
- },
747
- // removes a filter to the cohort filter set at the given index
748
- removeCohortFilter: (state, action)=>{
749
- const { index, field } = action.payload;
750
- const filters = state.cohort?.filters?.[index]?.root;
751
- if (!filters) {
752
- return;
753
- }
754
- const { [field]: _a, ...updated } = filters;
755
- return {
756
- cohort: {
757
- ...state.cohort,
758
- filters: {
759
- ...state.cohort.filters,
760
- [index]: {
761
- mode: state.cohort.filters[index].mode,
762
- root: updated
763
- }
764
- }
765
- }
766
- };
767
- },
768
- // removes all filters from the cohort filter set at the given index
769
- clearCohortFilters: (state, action)=>{
770
- const { index } = action.payload;
771
- return {
772
- cohort: {
773
- ...state.cohort,
774
- filters: {
775
- ...state.cohort.filters,
776
- [index]: {
777
- // empty filter set
778
- mode: 'and',
779
- root: {}
780
- }
781
- }
782
- }
783
- };
784
- }
785
- }
786
- });
787
- // Filter actions: addFilter, removeFilter, updateFilter
788
- const { updateCohortFilter, setCohortFilter, setCohortIndexFilters, removeCohortFilter, clearCohortFilters } = cohortSlice.actions;
789
- const selectCohortFilters = (state)=>state.cohorts.cohort.filters;
790
- const selectCurrentCohortId = (state)=>state.cohorts.cohort.id;
791
- const selectCurrentCohort = (state)=>state.cohorts.cohort;
792
- const selectCurrentCohortName = (state)=>state.cohorts.cohort.name;
793
- /**
794
- * Select a filter by its name from the current cohort. If the filter is not found
795
- * returns undefined.
796
- * @param state - Core
797
- * @param index which cohort index to select from
798
- * @param name name of the filter to select
799
- */ const selectIndexedFilterByName = (state, index, name)=>{
800
- return state.cohorts.cohort.filters[index]?.root[name];
801
- };
802
- const EmptyFilterSet = {
803
- mode: 'and',
804
- root: {}
805
- };
806
- /**
807
- * Select a filter from the index.
808
- * returns undefined.
809
- * @param state - Core
810
- * @param index which cohort index to select from
811
- */ const selectIndexFilters = (state, index)=>{
812
- return state.cohorts.cohort.filters?.[index] ?? EmptyFilterSet; // TODO: check if this is undefined
813
- };
814
- const cohortReducer = cohortSlice.reducer;
815
-
816
709
  const isFileItem = (item)=>{
817
710
  return item && 'guid' in item;
818
711
  };
@@ -1370,17 +1263,17 @@ const useDataLibrary = (useApi)=>{
1370
1263
  };
1371
1264
  };
1372
1265
 
1373
- const initialState$1 = {};
1266
+ const initialState$4 = {};
1374
1267
  const dataLibrarySlice = toolkit.createSlice({
1375
1268
  name: 'dataLibrary',
1376
- initialState: initialState$1,
1269
+ initialState: initialState$4,
1377
1270
  reducers: {
1378
1271
  setDataLibraryListSelection: (state, action)=>{
1379
1272
  const { listId, itemIds } = action.payload;
1380
1273
  state[listId] = itemIds;
1381
1274
  },
1382
1275
  clearDataLibrarySelection: ()=>{
1383
- return initialState$1;
1276
+ return initialState$4;
1384
1277
  }
1385
1278
  }
1386
1279
  });
@@ -1446,7 +1339,7 @@ const isTimeGreaterThan = (startTime, minutes)=>{
1446
1339
  };
1447
1340
 
1448
1341
  const NO_WORKSPACE_ID = 'none';
1449
- const initialState = {
1342
+ const initialState$3 = {
1450
1343
  id: NO_WORKSPACE_ID,
1451
1344
  status: WorkspaceStatus.NotFound,
1452
1345
  requestedStatus: RequestedWorkspaceStatus.Unset,
@@ -1454,7 +1347,7 @@ const initialState = {
1454
1347
  };
1455
1348
  const slice = toolkit.createSlice({
1456
1349
  name: 'ActiveWorkspace',
1457
- initialState,
1350
+ initialState: initialState$3,
1458
1351
  reducers: {
1459
1352
  setActiveWorkspaceId: (state, action)=>{
1460
1353
  state = {
@@ -1548,6 +1441,14 @@ const guppyApiReducer = guppyApi.reducer;
1548
1441
  const isOperationWithField = (operation)=>{
1549
1442
  return operation?.field !== undefined;
1550
1443
  };
1444
+ const isOperatorWithFieldAndArrayOfOperands = (operation)=>{
1445
+ if (typeof operation === 'object' && operation !== null && 'operands' in operation && Array.isArray(operation.operands) && 'field' in operation && typeof operation.field === 'string' // Assuming `field` should be a string
1446
+ ) {
1447
+ const { operator } = operation.operator;
1448
+ return operator === 'in' || operator === 'exclude' || operator === 'excludeifany';
1449
+ }
1450
+ return false;
1451
+ };
1551
1452
  const extractFilterValue = (op)=>{
1552
1453
  const valueExtractorHandler = new ValueExtractorHandler();
1553
1454
  return handleOperation(valueExtractorHandler, op);
@@ -1729,6 +1630,12 @@ const isFilterSet = (input)=>{
1729
1630
  }
1730
1631
  return true;
1731
1632
  };
1633
+ function isUnion(value) {
1634
+ return typeof value === 'object' && value !== null && value.operator === 'or' && Array.isArray(value.operands);
1635
+ }
1636
+ function isIntersection(value) {
1637
+ return typeof value === 'object' && value !== null && value.operator === 'and' && Array.isArray(value.operands);
1638
+ }
1732
1639
 
1733
1640
  const FieldNameOverrides = {};
1734
1641
  const COMMON_PREPOSITIONS = [
@@ -1793,67 +1700,250 @@ const trimFirstFieldNameToTitle = (fieldName, trim = false)=>{
1793
1700
  ];
1794
1701
  };
1795
1702
 
1796
- const statusEndpoint = '/_status';
1797
- const processHistogramResponse = (data)=>{
1798
- const valueData = jsonpathPlus.JSONPath({
1799
- json: data,
1800
- path: '$..histogram',
1801
- resultType: 'value'
1802
- });
1803
- const pointerData = jsonpathPlus.JSONPath({
1804
- json: data,
1805
- path: '$..histogram',
1806
- resultType: 'pointer'
1807
- });
1808
- const results = pointerData.reduce((acc, element, idx)=>{
1809
- const key = element.slice(1).replace(/\/histogram/g, '').replace(/\//g, '.');
1810
- return {
1811
- ...acc,
1812
- [key]: valueData[idx]
1813
- };
1814
- }, {});
1815
- return results;
1816
- };
1817
- const fetchJson = async (url)=>{
1818
- const res = await fetch(url, {
1819
- method: 'GET',
1820
- headers: {
1821
- 'Content-type': 'application/json'
1822
- }
1703
+ /**
1704
+ * Flattens a deep nested JSON object skipping
1705
+ * the first level to avoid potentially flattening
1706
+ * non-nested data.
1707
+ * @param {JSON} json
1708
+ */ function flattenJson(json) {
1709
+ const flattenedJson = [];
1710
+ Object.keys(json).forEach((key)=>{
1711
+ flattenedJson.push(flat.flatten(json[key], {
1712
+ delimiter: '_'
1713
+ }));
1823
1714
  });
1824
- if (!res.ok) throw new Error('An error occurred while fetching the data.');
1825
- return await res.json();
1826
- };
1827
- const useGetStatus = ()=>{
1828
- const fetcher = ()=>fetchJson(`${GEN3_GUPPY_API}${statusEndpoint}`);
1829
- return useSWR('explorerStatus', fetcher);
1830
- };
1715
+ return flattenedJson;
1716
+ }
1831
1717
  /**
1832
- * The main endpoint used in templating Exploration page queries.
1833
- * Includes table, filter and aggregation query types and leverages guppyApi defined in ./gupplApi.ts
1834
- * Query templates support filters where applicable
1718
+ * Converts JSON based on a config.
1719
+ * @param {JSON} json
1720
+ * @param {Object} config
1721
+ */ async function conversion(json, config) {
1722
+ return Papa.unparse(json, config);
1723
+ }
1724
+ /**
1725
+ * Converts JSON to a specified file format.
1726
+ * Defaults to JSON if file format is not supported.
1727
+ * @param {JSON} json
1728
+ * @param {string} format
1729
+ */ async function jsonToFormat(json, format) {
1730
+ if (Object.keys(FILE_DELIMITERS).includes(format)) {
1731
+ const flatJson = await flattenJson(json);
1732
+ const data = await conversion(flatJson, {
1733
+ delimiter: FILE_DELIMITERS[format]
1734
+ });
1735
+ return data;
1736
+ }
1737
+ return json;
1738
+ }
1739
+
1740
+ /**
1741
+ * Prepares a URL for downloading by appending '/download' to the provided apiUrl.
1835
1742
  *
1836
- * @param endpoints - Defines endpoints used in Exploration page:
1837
- * @param getAllFieldsForType - A mapping query that returns all property key names vertex types specified.
1838
- * @see https://github.com/uc-cdis/guppy/blob/master/doc/queries.md#mapping-query
1839
- * @param getAccessibleData - An aggregation histogram counts query that filters based on access type
1840
- * @see https://github.com/uc-cdis/guppy/blob/master/doc/queries.md#accessibility-argument-for-regular-tier-access-level
1841
- * @param getRawDataAndTotalCounts - Queries both _totalCount for selected vertex types and
1842
- * tabular results containing the raw data in the rows of selected vertex types
1843
- * @see https://github.com/uc-cdis/guppy/blob/master/doc/queries.md#1-total-count-aggregation
1844
- * @param getAggs - An aggregated histogram counts query which outputs vertex property frequencies
1845
- * @param getSubAggs - TODO: not sure what this one does. Looks like nested aggregation
1846
- * @param getCounts - Returns total counts of a vertex type
1847
- * @returns: A guppy API endpoint for templating queriable data displayed on the exploration page
1848
- */ const explorerApi = guppyApi.injectEndpoints({
1849
- endpoints: (builder)=>({
1850
- getAllFieldsForType: builder.query({
1851
- query: (type)=>({
1852
- query: `{ _mapping ${type} } }`
1853
- }),
1854
- transformResponse: (response, _meta, params)=>{
1855
- return response[params.type];
1856
- }
1743
+ * @param {string} apiUrl - The base URL to be used for preparing the download URL.
1744
+ * @returns {URL} - The prepared download URL as a URL object.
1745
+ */ const prepareUrl$1 = (apiUrl)=>`${apiUrl}/download`;
1746
+ /**
1747
+ * Prepares a fetch configuration object for downloading files from Guppy.
1748
+ *
1749
+ * @param {GuppyFileDownloadRequestParams} parameters - The parameters to include in the request body.
1750
+ * @param {string} csrfToken - The CSRF token to include in the request headers.
1751
+ * @returns {FetchConfig} - The prepared fetch configuration object.
1752
+ */ const prepareFetchConfig = (parameters, csrfToken)=>{
1753
+ return {
1754
+ method: 'POST',
1755
+ headers: {
1756
+ 'Content-Type': 'application/json',
1757
+ ...csrfToken !== undefined && {
1758
+ 'X-CSRF-Token': csrfToken
1759
+ }
1760
+ },
1761
+ body: JSON.stringify({
1762
+ type: parameters.type,
1763
+ filter: convertFilterSetToGqlFilter(parameters.filter),
1764
+ accessibility: parameters.accessibility,
1765
+ fields: parameters?.fields,
1766
+ sort: parameters?.sort
1767
+ })
1768
+ };
1769
+ };
1770
+ /**
1771
+ * Downloads a file from Guppy using the provided parameters.
1772
+ * It will optionally convert the data to the specified format.
1773
+ *
1774
+ * @param {DownloadFromGuppyParams} parameters - The parameters to use for the download request.
1775
+ * @param onStart - The function to call when the download starts.
1776
+ * @param onDone - The function to call when the download is done.
1777
+ * @param onError - The function to call when the download fails.
1778
+ * @param onAbort - The function to call when the download is aborted.
1779
+ * @param signal - AbortSignal to use for the request.
1780
+ */ const downloadFromGuppyToBlob = async ({ parameters, onStart = ()=>null, onDone = (_)=>null, onError = (_)=>null, onAbort = ()=>null, signal = undefined })=>{
1781
+ const csrfToken = selectCSRFToken(coreStore.getState());
1782
+ onStart?.();
1783
+ const url = prepareUrl$1(GEN3_GUPPY_API);
1784
+ const fetchConfig = prepareFetchConfig(parameters, csrfToken);
1785
+ fetch(url.toString(), {
1786
+ ...fetchConfig,
1787
+ ...signal ? {
1788
+ signal: signal
1789
+ } : {}
1790
+ }).then(async (response)=>{
1791
+ if (!response.ok) {
1792
+ throw new Error(response.statusText);
1793
+ }
1794
+ let jsonData = await response.json();
1795
+ if (parameters?.rootPath && parameters.rootPath) {
1796
+ // if rootPath is provided, extract the data from the rootPath
1797
+ jsonData = jsonpathPlus.JSONPath({
1798
+ json: jsonData,
1799
+ path: `$.[${parameters.rootPath}]`,
1800
+ resultType: 'value'
1801
+ });
1802
+ }
1803
+ // convert the data to the specified format and return a Blob
1804
+ let str = '';
1805
+ if (parameters.format === 'json') {
1806
+ str = JSON.stringify(jsonData);
1807
+ } else {
1808
+ const convertedData = await jsonToFormat(jsonData, parameters.format);
1809
+ if (isJSONObject(convertedData)) {
1810
+ str = JSON.stringify(convertedData, null, 2);
1811
+ } else {
1812
+ str = convertedData;
1813
+ }
1814
+ }
1815
+ return new Blob([
1816
+ str
1817
+ ], {
1818
+ type: 'application/json'
1819
+ });
1820
+ }).then((blob)=>onDone?.(blob)).catch((error)=>{
1821
+ // Abort is handle as an exception
1822
+ if (error.name == 'AbortError') {
1823
+ // handle abort()
1824
+ onAbort?.();
1825
+ }
1826
+ onError?.(error);
1827
+ });
1828
+ };
1829
+ const downloadJSONDataFromGuppy = async ({ parameters, onAbort = ()=>null, signal = undefined })=>{
1830
+ const csrfToken = selectCSRFToken(coreStore.getState());
1831
+ const url = prepareUrl$1(GEN3_GUPPY_API);
1832
+ const fetchConfig = prepareFetchConfig(parameters, csrfToken);
1833
+ try {
1834
+ const response = await fetch(url.toString(), {
1835
+ ...fetchConfig,
1836
+ ...signal ? {
1837
+ signal: signal
1838
+ } : {}
1839
+ });
1840
+ let jsonData = await response.json();
1841
+ if (parameters?.rootPath && parameters.rootPath) {
1842
+ // if rootPath is provided, extract the data from the rootPath
1843
+ jsonData = jsonpathPlus.JSONPath({
1844
+ json: jsonData,
1845
+ path: `$.[${parameters.rootPath}]`,
1846
+ resultType: 'value'
1847
+ });
1848
+ }
1849
+ // convert the data to the specified format and return a Blob
1850
+ return jsonData;
1851
+ } catch (error) {
1852
+ // Abort is handle as an exception
1853
+ if (error.name == 'AbortError') {
1854
+ // handle abort()
1855
+ onAbort?.();
1856
+ }
1857
+ throw new Error(error);
1858
+ }
1859
+ };
1860
+ const useGetIndexFields = (index)=>{
1861
+ const { data } = useGetFieldsForIndexQuery(index);
1862
+ return data ?? [];
1863
+ };
1864
+ const groupSharedFields = (data)=>{
1865
+ const reverseIndex = {};
1866
+ // Build reverse index: track which root keys contain each element
1867
+ for(const rootKey in data){
1868
+ data[rootKey].forEach((value)=>{
1869
+ if (!reverseIndex[value]) {
1870
+ reverseIndex[value] = new Set();
1871
+ }
1872
+ reverseIndex[value].add(rootKey);
1873
+ });
1874
+ }
1875
+ return Object.entries(reverseIndex).reduce((acc, [field, indexSet])=>{
1876
+ if (indexSet.size > 1) {
1877
+ acc[field] = Array.from(indexSet).map((x)=>({
1878
+ index: x,
1879
+ field: field
1880
+ }));
1881
+ }
1882
+ return acc;
1883
+ }, {});
1884
+ };
1885
+
1886
+ const statusEndpoint = '/_status';
1887
+ const processHistogramResponse = (data)=>{
1888
+ const valueData = jsonpathPlus.JSONPath({
1889
+ json: data,
1890
+ path: '$..histogram',
1891
+ resultType: 'value'
1892
+ });
1893
+ const pointerData = jsonpathPlus.JSONPath({
1894
+ json: data,
1895
+ path: '$..histogram',
1896
+ resultType: 'pointer'
1897
+ });
1898
+ const results = pointerData.reduce((acc, element, idx)=>{
1899
+ const key = element.slice(1).replace(/\/histogram/g, '').replace(/\//g, '.');
1900
+ return {
1901
+ ...acc,
1902
+ [key]: valueData[idx]
1903
+ };
1904
+ }, {});
1905
+ return results;
1906
+ };
1907
+ const fetchJson = async (url)=>{
1908
+ const res = await fetch(url, {
1909
+ method: 'GET',
1910
+ headers: {
1911
+ 'Content-type': 'application/json'
1912
+ }
1913
+ });
1914
+ if (!res.ok) throw new Error('An error occurred while fetching the data.');
1915
+ return await res.json();
1916
+ };
1917
+ const useGetStatus = ()=>{
1918
+ const fetcher = ()=>fetchJson(`${GEN3_GUPPY_API}${statusEndpoint}`);
1919
+ return useSWR('explorerStatus', fetcher);
1920
+ };
1921
+ /**
1922
+ * The main endpoint used in templating Exploration page queries.
1923
+ * Includes table, filter and aggregation query types and leverages guppyApi defined in ./gupplApi.ts
1924
+ * Query templates support filters where applicable
1925
+ *
1926
+ * @param endpoints - Defines endpoints used in Exploration page:
1927
+ * @param getAllFieldsForType - A mapping query that returns all property key names vertex types specified.
1928
+ * @see https://github.com/uc-cdis/guppy/blob/master/doc/queries.md#mapping-query
1929
+ * @param getAccessibleData - An aggregation histogram counts query that filters based on access type
1930
+ * @see https://github.com/uc-cdis/guppy/blob/master/doc/queries.md#accessibility-argument-for-regular-tier-access-level
1931
+ * @param getRawDataAndTotalCounts - Queries both _totalCount for selected vertex types and
1932
+ * tabular results containing the raw data in the rows of selected vertex types
1933
+ * @see https://github.com/uc-cdis/guppy/blob/master/doc/queries.md#1-total-count-aggregation
1934
+ * @param getAggs - An aggregated histogram counts query which outputs vertex property frequencies
1935
+ * @param getSubAggs - TODO: not sure what this one does. Looks like nested aggregation
1936
+ * @param getCounts - Returns total counts of a vertex type
1937
+ * @returns: A guppy API endpoint for templating queryable data displayed on the exploration page
1938
+ */ const explorerApi = guppyApi.injectEndpoints({
1939
+ endpoints: (builder)=>({
1940
+ getAllFieldsForType: builder.query({
1941
+ query: (type)=>({
1942
+ query: `{ _mapping ${type} } }`
1943
+ }),
1944
+ transformResponse: (response, _meta, params)=>{
1945
+ return response[params.type];
1946
+ }
1857
1947
  }),
1858
1948
  getAccessibleData: builder.query({
1859
1949
  query: ({ type, fields, accessType })=>{
@@ -1946,7 +2036,32 @@ const useGetStatus = ()=>{
1946
2036
  return queryBody;
1947
2037
  },
1948
2038
  transformResponse: (response, _meta, args)=>{
1949
- return processHistogramResponse(response.data._aggregation[args.type]);
2039
+ return processHistogramResponse(response?.data?._aggregation[args.type] ?? {});
2040
+ }
2041
+ }),
2042
+ getAggsNoFilterSelf: builder.query({
2043
+ query: ({ type, fields, filters, accessibility = Accessibility.ALL })=>{
2044
+ const queryStart = isFilterEmpty(filters) ? `
2045
+ query getAggs {
2046
+ _aggregation {
2047
+ ${type} (accessibility: ${accessibility}) {` : `query getAggs ($filter: JSON) {
2048
+ _aggregation {
2049
+ ${type} (filter: $filter, filterSelf: true, accessibility: ${accessibility}) {`;
2050
+ const query = `${queryStart}
2051
+ ${fields.map((field)=>histogramQueryStrForEachField(field))}
2052
+ }
2053
+ }
2054
+ }`;
2055
+ const queryBody = {
2056
+ query: query,
2057
+ variables: {
2058
+ filter: convertFilterSetToGqlFilter(filters)
2059
+ }
2060
+ };
2061
+ return queryBody;
2062
+ },
2063
+ transformResponse: (response, _meta, args)=>{
2064
+ return processHistogramResponse(response?.data?._aggregation[args.type] ?? {});
1950
2065
  }
1951
2066
  }),
1952
2067
  getSubAggs: builder.query({
@@ -1971,7 +2086,7 @@ const useGetStatus = ()=>{
1971
2086
  };
1972
2087
  },
1973
2088
  transformResponse: (response, _meta, args)=>{
1974
- return processHistogramResponse(response.data._aggregation[args.type]);
2089
+ return processHistogramResponse(response?.data?._aggregation[args.type] ?? {});
1975
2090
  }
1976
2091
  }),
1977
2092
  getCounts: builder.query({
@@ -1995,7 +2110,13 @@ const useGetStatus = ()=>{
1995
2110
  };
1996
2111
  },
1997
2112
  transformResponse: (response, _meta, args)=>{
1998
- return response.data._aggregation[args.type]._totalCount;
2113
+ if (!response.data || !response.data._aggregation) {
2114
+ throw new Error('Invalid response: Missing data or _aggregation field');
2115
+ }
2116
+ if (!(args.type in response.data._aggregation)) {
2117
+ throw new Error(`Invalid response: Missing expected key '${args.type}' in _aggregation`);
2118
+ }
2119
+ return response.data._aggregation[args.type]._totalCount ?? 0;
1999
2120
  }
2000
2121
  }),
2001
2122
  getFieldCountSummary: builder.query({
@@ -2026,7 +2147,7 @@ const useGetStatus = ()=>{
2026
2147
  query: (index)=>{
2027
2148
  return {
2028
2149
  query: `{
2029
- _mapping ${index}
2150
+ _mapping { ${index} }
2030
2151
  }`
2031
2152
  };
2032
2153
  },
@@ -2034,6 +2155,21 @@ const useGetStatus = ()=>{
2034
2155
  return response['_mapping'];
2035
2156
  }
2036
2157
  }),
2158
+ getSharedFieldsForIndex: builder.query({
2159
+ query: (indices)=>{
2160
+ return {
2161
+ query: `{
2162
+ _mapping { ${indices.join(' ')} }
2163
+ }`
2164
+ };
2165
+ },
2166
+ transformResponse: (response)=>{
2167
+ if ('_mapping' in response.data) {
2168
+ return groupSharedFields(response.data['_mapping']);
2169
+ }
2170
+ return {};
2171
+ }
2172
+ }),
2037
2173
  generalGQL: builder.query({
2038
2174
  query: ({ query, variables })=>{
2039
2175
  return {
@@ -2104,169 +2240,7 @@ const useGetArrayTypes = ()=>{
2104
2240
  return data ? data['indices'] : {};
2105
2241
  }
2106
2242
  };
2107
- const { useGetRawDataAndTotalCountsQuery, useGetAccessibleDataQuery, useGetAllFieldsForTypeQuery, useGetAggsQuery, useLazyGetAggsQuery, useGetSubAggsQuery, useGetCountsQuery, useGetFieldCountSummaryQuery, useGetFieldsForIndexQuery, useGeneralGQLQuery, useLazyGeneralGQLQuery } = explorerApi;
2108
-
2109
- /**
2110
- * Flattens a deep nested JSON object skipping
2111
- * the first level to avoid potentially flattening
2112
- * non-nested data.
2113
- * @param {JSON} json
2114
- */ function flattenJson(json) {
2115
- const flattenedJson = [];
2116
- Object.keys(json).forEach((key)=>{
2117
- flattenedJson.push(flat.flatten(json[key], {
2118
- delimiter: '_'
2119
- }));
2120
- });
2121
- return flattenedJson;
2122
- }
2123
- /**
2124
- * Converts JSON based on a config.
2125
- * @param {JSON} json
2126
- * @param {Object} config
2127
- */ async function conversion(json, config) {
2128
- return Papa.unparse(json, config);
2129
- }
2130
- /**
2131
- * Converts JSON to a specified file format.
2132
- * Defaults to JSON if file format is not supported.
2133
- * @param {JSON} json
2134
- * @param {string} format
2135
- */ async function jsonToFormat(json, format) {
2136
- if (Object.keys(FILE_DELIMITERS).includes(format)) {
2137
- const flatJson = await flattenJson(json);
2138
- const data = await conversion(flatJson, {
2139
- delimiter: FILE_DELIMITERS[format]
2140
- });
2141
- return data;
2142
- }
2143
- return json;
2144
- }
2145
-
2146
- /**
2147
- * Prepares a URL for downloading by appending '/download' to the provided apiUrl.
2148
- *
2149
- * @param {string} apiUrl - The base URL to be used for preparing the download URL.
2150
- * @returns {URL} - The prepared download URL as a URL object.
2151
- */ const prepareUrl$1 = (apiUrl)=>`${apiUrl}/download`;
2152
- /**
2153
- * Prepares a fetch configuration object for downloading files from Guppy.
2154
- *
2155
- * @param {GuppyFileDownloadRequestParams} parameters - The parameters to include in the request body.
2156
- * @param {string} csrfToken - The CSRF token to include in the request headers.
2157
- * @returns {FetchConfig} - The prepared fetch configuration object.
2158
- */ const prepareFetchConfig = (parameters, csrfToken)=>{
2159
- return {
2160
- method: 'POST',
2161
- headers: {
2162
- 'Content-Type': 'application/json',
2163
- ...csrfToken !== undefined && {
2164
- 'X-CSRF-Token': csrfToken
2165
- }
2166
- },
2167
- body: JSON.stringify({
2168
- type: parameters.type,
2169
- filter: convertFilterSetToGqlFilter(parameters.filter),
2170
- accessibility: parameters.accessibility,
2171
- fields: parameters?.fields,
2172
- sort: parameters?.sort
2173
- })
2174
- };
2175
- };
2176
- /**
2177
- * Downloads a file from Guppy using the provided parameters.
2178
- * It will optionally convert the data to the specified format.
2179
- *
2180
- * @param {DownloadFromGuppyParams} parameters - The parameters to use for the download request.
2181
- * @param onStart - The function to call when the download starts.
2182
- * @param onDone - The function to call when the download is done.
2183
- * @param onError - The function to call when the download fails.
2184
- * @param onAbort - The function to call when the download is aborted.
2185
- * @param signal - AbortSignal to use for the request.
2186
- */ const downloadFromGuppyToBlob = async ({ parameters, onStart = ()=>null, onDone = (_)=>null, onError = (_)=>null, onAbort = ()=>null, signal = undefined })=>{
2187
- const csrfToken = selectCSRFToken(coreStore.getState());
2188
- onStart?.();
2189
- const url = prepareUrl$1(GEN3_GUPPY_API);
2190
- const fetchConfig = prepareFetchConfig(parameters, csrfToken);
2191
- fetch(url.toString(), {
2192
- ...fetchConfig,
2193
- ...signal ? {
2194
- signal: signal
2195
- } : {}
2196
- }).then(async (response)=>{
2197
- if (!response.ok) {
2198
- throw new Error(response.statusText);
2199
- }
2200
- let jsonData = await response.json();
2201
- if (parameters?.rootPath && parameters.rootPath) {
2202
- // if rootPath is provided, extract the data from the rootPath
2203
- jsonData = jsonpathPlus.JSONPath({
2204
- json: jsonData,
2205
- path: `$.[${parameters.rootPath}]`,
2206
- resultType: 'value'
2207
- });
2208
- }
2209
- // convert the data to the specified format and return a Blob
2210
- let str = '';
2211
- if (parameters.format === 'json') {
2212
- str = JSON.stringify(jsonData);
2213
- } else {
2214
- const convertedData = await jsonToFormat(jsonData, parameters.format);
2215
- if (isJSONObject(convertedData)) {
2216
- str = JSON.stringify(convertedData, null, 2);
2217
- } else {
2218
- str = convertedData;
2219
- }
2220
- }
2221
- return new Blob([
2222
- str
2223
- ], {
2224
- type: 'application/json'
2225
- });
2226
- }).then((blob)=>onDone?.(blob)).catch((error)=>{
2227
- // Abort is handle as an exception
2228
- if (error.name == 'AbortError') {
2229
- // handle abort()
2230
- onAbort?.();
2231
- }
2232
- onError?.(error);
2233
- });
2234
- };
2235
- const downloadJSONDataFromGuppy = async ({ parameters, onAbort = ()=>null, signal = undefined })=>{
2236
- const csrfToken = selectCSRFToken(coreStore.getState());
2237
- const url = prepareUrl$1(GEN3_GUPPY_API);
2238
- const fetchConfig = prepareFetchConfig(parameters, csrfToken);
2239
- try {
2240
- const response = await fetch(url.toString(), {
2241
- ...fetchConfig,
2242
- ...signal ? {
2243
- signal: signal
2244
- } : {}
2245
- });
2246
- let jsonData = await response.json();
2247
- if (parameters?.rootPath && parameters.rootPath) {
2248
- // if rootPath is provided, extract the data from the rootPath
2249
- jsonData = jsonpathPlus.JSONPath({
2250
- json: jsonData,
2251
- path: `$.[${parameters.rootPath}]`,
2252
- resultType: 'value'
2253
- });
2254
- }
2255
- // convert the data to the specified format and return a Blob
2256
- return jsonData;
2257
- } catch (error) {
2258
- // Abort is handle as an exception
2259
- if (error.name == 'AbortError') {
2260
- // handle abort()
2261
- onAbort?.();
2262
- }
2263
- throw new Error(error);
2264
- }
2265
- };
2266
- const useGetIndexFields = (index)=>{
2267
- const { data } = useGetFieldsForIndexQuery(index);
2268
- return data ?? [];
2269
- };
2243
+ const { useGetRawDataAndTotalCountsQuery, useGetAccessibleDataQuery, useGetAllFieldsForTypeQuery, useGetAggsQuery, useGetAggsNoFilterSelfQuery, useLazyGetAggsQuery, useGetSubAggsQuery, useGetCountsQuery, useGetFieldCountSummaryQuery, useGetFieldsForIndexQuery, useGetSharedFieldsForIndexQuery, useGeneralGQLQuery, useLazyGeneralGQLQuery } = explorerApi;
2270
2244
 
2271
2245
  /**
2272
2246
  * Creates a Guppy API for fetching bulk (> 10K rows) elasticsearch data
@@ -2302,13 +2276,230 @@ const useGetIndexFields = (index)=>{
2302
2276
  });
2303
2277
  const { useDownloadFromGuppyMutation } = downloadRequestApi;
2304
2278
 
2279
+ const EmptyCohort = {
2280
+ id: 'default',
2281
+ name: 'Filters',
2282
+ filters: {},
2283
+ modified_datetime: new Date().toISOString()
2284
+ };
2285
+ const initialCohortState = {
2286
+ cohort: {
2287
+ ...EmptyCohort
2288
+ }
2289
+ };
2290
+ // TODO: start using this adapter
2291
+ /*
2292
+ const cohortsAdapter = createEntityAdapter<Cohort>({
2293
+ sortComparer: (a, b) => {
2294
+ if (a.modified_datetime <= b.modified_datetime) return 1;
2295
+ else return -1;
2296
+ },
2297
+ });
2298
+ */ /**
2299
+ * Redux slice for cohort filters
2300
+ */ const cohortSlice = toolkit.createSlice({
2301
+ name: 'cohort',
2302
+ initialState: initialCohortState,
2303
+ reducers: {
2304
+ // adds a filter to the cohort filter set at the given index
2305
+ updateCohortFilter: (state, action)=>{
2306
+ const { index, field, filter } = action.payload;
2307
+ return {
2308
+ cohort: {
2309
+ ...state.cohort,
2310
+ filters: {
2311
+ ...state.cohort.filters,
2312
+ [index]: {
2313
+ mode: state.cohort.filters?.[index]?.mode ?? 'and',
2314
+ root: {
2315
+ ...state.cohort.filters?.[index]?.root ?? {},
2316
+ [field]: filter
2317
+ }
2318
+ }
2319
+ }
2320
+ }
2321
+ };
2322
+ },
2323
+ setCohortFilter: (state, action)=>{
2324
+ const { index, filters } = action.payload;
2325
+ return {
2326
+ cohort: {
2327
+ ...state.cohort,
2328
+ filters: {
2329
+ ...state.cohort.filters,
2330
+ [index]: filters
2331
+ }
2332
+ }
2333
+ };
2334
+ },
2335
+ setCohortIndexFilters: (state, action)=>{
2336
+ return {
2337
+ cohort: {
2338
+ ...state.cohort,
2339
+ filters: {
2340
+ ...action.payload.filters
2341
+ }
2342
+ }
2343
+ };
2344
+ },
2345
+ // removes a filter to the cohort filter set at the given index
2346
+ removeCohortFilter: (state, action)=>{
2347
+ const { index, field } = action.payload;
2348
+ const filters = state.cohort?.filters?.[index]?.root;
2349
+ if (!filters) {
2350
+ return;
2351
+ }
2352
+ const { [field]: _a, ...updated } = filters;
2353
+ return {
2354
+ cohort: {
2355
+ ...state.cohort,
2356
+ filters: {
2357
+ ...state.cohort.filters,
2358
+ [index]: {
2359
+ mode: state.cohort.filters[index].mode,
2360
+ root: updated
2361
+ }
2362
+ }
2363
+ }
2364
+ };
2365
+ },
2366
+ // removes all filters from the cohort filter set at the given index
2367
+ clearCohortFilters: (state, action)=>{
2368
+ const { index } = action.payload;
2369
+ return {
2370
+ cohort: {
2371
+ ...state.cohort,
2372
+ filters: {
2373
+ ...state.cohort.filters,
2374
+ [index]: {
2375
+ // empty filter set
2376
+ mode: 'and',
2377
+ root: {}
2378
+ }
2379
+ }
2380
+ }
2381
+ };
2382
+ }
2383
+ }
2384
+ });
2385
+ // Filter actions: addFilter, removeFilter, updateFilter
2386
+ const { updateCohortFilter, setCohortFilter, setCohortIndexFilters, removeCohortFilter, clearCohortFilters } = cohortSlice.actions;
2387
+ const selectCohortFilters = (state)=>state.cohorts.cohort.cohort.filters;
2388
+ const selectCurrentCohortId = (state)=>state.cohorts.cohort.cohort.id;
2389
+ const selectCurrentCohort = (state)=>state.cohorts.cohort.cohort;
2390
+ const selectCurrentCohortName = (state)=>state.cohorts.cohort.cohort.name;
2391
+ /**
2392
+ * Select a filter by its name from the current cohort. If the filter is not found
2393
+ * returns undefined.
2394
+ * @param state - Core
2395
+ * @param index which cohort index to select from
2396
+ * @param name name of the filter to select
2397
+ */ const selectIndexedFilterByName = (state, index, name)=>{
2398
+ return state.cohorts.cohort.cohort.filters[index]?.root[name];
2399
+ };
2400
+ const EmptyFilterSet = {
2401
+ mode: 'and',
2402
+ root: {}
2403
+ };
2404
+ /**
2405
+ * Select a filter from the index.
2406
+ * returns undefined.
2407
+ * @param state - Core
2408
+ * @param index which cohort index to select from
2409
+ */ const selectIndexFilters = (state, index)=>{
2410
+ return state.cohorts.cohort.cohort.filters?.[index] ?? EmptyFilterSet; // TODO: check if this is undefined
2411
+ };
2412
+ const cohortReducer = cohortSlice.reducer;
2413
+
2414
+ const initialState$2 = {};
2415
+ const expandSlice$1 = toolkit.createSlice({
2416
+ name: 'CohortBuilder/filterExpand',
2417
+ initialState: initialState$2,
2418
+ reducers: {
2419
+ toggleCohortBuilderCategoryFilter: (state, action)=>{
2420
+ return {
2421
+ ...state,
2422
+ [action.payload.index]: {
2423
+ ...state[action.payload.index],
2424
+ [action.payload.field]: action.payload.expanded
2425
+ }
2426
+ };
2427
+ },
2428
+ toggleCohortBuilderAllFilters: (state, action)=>{
2429
+ return {
2430
+ ...state,
2431
+ [action.payload.index]: Object.keys(state[action.payload.index]).reduce((acc, k)=>{
2432
+ acc[k] = action.payload.expand;
2433
+ return acc;
2434
+ }, {})
2435
+ };
2436
+ }
2437
+ }
2438
+ });
2439
+ const cohortBuilderFiltersExpandedReducer = expandSlice$1.reducer;
2440
+ const { toggleCohortBuilderCategoryFilter, toggleCohortBuilderAllFilters } = expandSlice$1.actions;
2441
+ const selectCohortFilterExpanded = (state, index, field)=>state.cohorts.filtersExpanded?.[index]?.[field];
2442
+ const selectAllCohortFiltersCollapsed = (state, index)=>index in state.cohorts.filtersExpanded ? Object.values(state.cohorts.filtersExpanded?.[index]).every((e)=>!e) : false;
2443
+
2444
+ const initialState$1 = {};
2445
+ const expandSlice = toolkit.createSlice({
2446
+ name: 'CohortBuilder/filterCombineMode',
2447
+ initialState: initialState$1,
2448
+ reducers: {
2449
+ setCohortFilterCombineMode: (state, action)=>{
2450
+ return {
2451
+ ...state,
2452
+ [action.payload.index]: {
2453
+ ...state[action.payload.index],
2454
+ [action.payload.field]: action.payload.mode
2455
+ }
2456
+ };
2457
+ }
2458
+ }
2459
+ });
2460
+ const cohortBuilderFiltersCombineModeReducer = expandSlice.reducer;
2461
+ const { setCohortFilterCombineMode } = expandSlice.actions;
2462
+ const selectCohortFilterCombineMode = (state, index, field)=>state.cohorts.filtersCombineMode?.[index]?.[field] ?? 'or';
2463
+
2464
+ const initialState = {
2465
+ shouldShareFilters: false,
2466
+ sharedFiltersMap: {}
2467
+ };
2468
+ const cohortSharedFiltersSlice = toolkit.createSlice({
2469
+ name: 'cohortSharedFilters',
2470
+ initialState: initialState,
2471
+ reducers: {
2472
+ setShouldShareFilters: (state, action)=>{
2473
+ state.shouldShareFilters = action.payload;
2474
+ return state;
2475
+ },
2476
+ setSharedFilters: (state, action)=>{
2477
+ state.sharedFiltersMap = action.payload;
2478
+ }
2479
+ }
2480
+ });
2481
+ const selectShouldShareFilters = (state)=>state.cohorts.sharedFilters.shouldShareFilters;
2482
+ const selectSharedFilters = (state)=>state.cohorts.sharedFilters.sharedFiltersMap;
2483
+ const selectSharedFiltersForFields = (state, field)=>state.cohorts.sharedFilters.sharedFiltersMap?.[field] ?? [
2484
+ field
2485
+ ];
2486
+ const { setShouldShareFilters, setSharedFilters } = cohortSharedFiltersSlice.actions;
2487
+ const cohortSharedFiltersReducer = cohortSharedFiltersSlice.reducer;
2488
+
2489
+ const cohortReducers = toolkit.combineReducers({
2490
+ filtersExpanded: cohortBuilderFiltersExpandedReducer,
2491
+ filtersCombineMode: cohortBuilderFiltersCombineModeReducer,
2492
+ sharedFilters: cohortSharedFiltersReducer,
2493
+ cohort: cohortReducer
2494
+ });
2495
+
2305
2496
  const rootReducer = toolkit.combineReducers({
2306
2497
  gen3Services: gen3ServicesReducer,
2307
2498
  user: userReducer,
2308
2499
  gen3Apps: gen3AppReducer,
2309
2500
  drsHostnames: drsHostnamesReducer,
2310
2501
  modals: modalReducer,
2311
- cohorts: cohortReducer,
2502
+ cohorts: cohortReducers,
2312
2503
  activeWorkspace: activeWorkspaceReducer,
2313
2504
  dataLibrarySelection: dataLibrarySelectionReducer,
2314
2505
  [guppyApiSliceReducerPath]: guppyApiReducer,
@@ -2337,7 +2528,7 @@ const persistConfig = {
2337
2528
  version: 1,
2338
2529
  storage,
2339
2530
  whitelist: [
2340
- 'cohorts',
2531
+ 'cohort',
2341
2532
  'activeWorkspace'
2342
2533
  ]
2343
2534
  };
@@ -2362,7 +2553,7 @@ const coreStore = setupCoreStore();
2362
2553
  query.setupListeners(coreStore.dispatch);
2363
2554
 
2364
2555
  const isNotDefined = (x)=>{
2365
- return x === undefined || x === null || x === undefined;
2556
+ return x === undefined || x === null || x === void 0;
2366
2557
  };
2367
2558
  const isObject = (x)=>{
2368
2559
  return typeof x === 'object';
@@ -2381,51 +2572,14 @@ const isString = (x)=>{
2381
2572
  * @returns {URL} - The prepared download URL as a URL object.
2382
2573
  */ const prepareUrl = (apiUrl)=>new URL(apiUrl + '/download');
2383
2574
 
2384
- const HTTPErrorMessages = {
2385
- // 4xx Client Errors
2386
- 400: 'Bad Request',
2387
- 401: 'Unauthorized',
2388
- 402: 'Payment Required',
2389
- 403: 'Forbidden',
2390
- 404: 'Not Found',
2391
- 405: 'Method Not Allowed',
2392
- 406: 'Not Acceptable',
2393
- 407: 'Proxy Authentication Required',
2394
- 408: 'Request Timeout',
2395
- 409: 'Conflict',
2396
- 410: 'Gone',
2397
- 411: 'Length Required',
2398
- 412: 'Precondition Failed',
2399
- 413: 'Payload Too Large',
2400
- 414: 'URI Too Long',
2401
- 415: 'Unsupported Media Type',
2402
- 416: 'Range Not Satisfiable',
2403
- 417: 'Expectation Failed',
2404
- 418: "I'm a teapot",
2405
- 421: 'Misdirected Request',
2406
- 422: 'Unprocessable Entity',
2407
- 423: 'Locked',
2408
- 424: 'Failed Dependency',
2409
- 425: 'Too Early',
2410
- 426: 'Upgrade Required',
2411
- 428: 'Precondition Required',
2412
- 429: 'Too Many Requests',
2413
- 431: 'Request Header Fields Too Large',
2414
- 451: 'Unavailable For Legal Reasons',
2415
- // 5xx Server Errors
2416
- 500: 'Internal Server Error',
2417
- 501: 'Not Implemented',
2418
- 502: 'Bad Gateway',
2419
- 503: 'Service Unavailable',
2420
- 504: 'Gateway Timeout',
2421
- 505: 'HTTP Version Not Supported',
2422
- 506: 'Variant Also Negotiates',
2423
- 507: 'Insufficient Storage',
2424
- 508: 'Loop Detected',
2425
- 510: 'Not Extended',
2426
- 511: 'Network Authentication Required'
2427
- };
2428
- class HTTPError extends Error {
2575
+ const DEFAULT_METHOD = 'GET';
2576
+ const CONTENT_TYPE_HEADER = 'Content-Type';
2577
+ const CONTENT_TYPE_JSON = 'application/json';
2578
+ /**
2579
+ * Represents an error that occurs during an HTTP request.
2580
+ * Extends the built-in `Error` class to provide additional information
2581
+ * about the HTTP status code and optional response data.
2582
+ */ class HTTPError extends Error {
2429
2583
  constructor(status, message, responseData){
2430
2584
  super(message), this.status = status, this.responseData = responseData;
2431
2585
  this.name = 'HTTPError';
@@ -2435,15 +2589,16 @@ const fetchFencePresignedURL = async ({ guid, method = 'GET', onAbort = ()=>null
2435
2589
  const csrfToken = selectCSRFToken(coreStore.getState());
2436
2590
  const headers = new Headers();
2437
2591
  headers.set('Content-Type', 'application/json');
2438
- let accessToken = undefined;
2439
2592
  if (process.env.NODE_ENV === 'development') {
2440
2593
  // NOTE: This cookie can only be accessed from the client side
2441
2594
  // in development mode. Otherwise, the cookie is set as httpOnly
2442
- accessToken = cookiesNext.getCookie('credentials_token');
2595
+ const accessToken = cookiesNext.getCookie('credentials_token');
2596
+ if (accessToken) {
2597
+ headers.set('Authorization', `Bearer ${accessToken}`);
2598
+ }
2443
2599
  }
2444
2600
  if (csrfToken) headers.set('X-CSRF-Token', csrfToken);
2445
- if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`);
2446
- const url = `${GEN3_FENCE_API}/user/data/download/${guid}`;
2601
+ const url = `${GEN3_FENCE_API}/data/download/${guid}`;
2447
2602
  try {
2448
2603
  const response = await fetch(url, {
2449
2604
  method: method,
@@ -2476,6 +2631,67 @@ const fetchFencePresignedURL = async ({ guid, method = 'GET', onAbort = ()=>null
2476
2631
  throw error;
2477
2632
  }
2478
2633
  };
2634
+ /**
2635
+ * Retrieves a CSRF token from the server.
2636
+ *
2637
+ * This asynchronous function sends a GET request to the server's status endpoint
2638
+ * to fetch the CSRF token in the response. The token is expected to be included
2639
+ * in the JSON response under the `csrf_token` field.
2640
+ *
2641
+ * @returns {Promise<string | null>} A promise that resolves to the CSRF token as a string if successfully retrieved,
2642
+ * or null if the token is not present in the response.
2643
+ * @throws {HTTPError} Throws an HTTPError if the server response is not successful.
2644
+ */ const getCSRFToken = async ()=>{
2645
+ const requestHeaders = new Headers({
2646
+ [CONTENT_TYPE_HEADER]: CONTENT_TYPE_JSON
2647
+ });
2648
+ const response = await fetch(`${GEN3_API}/_status`, {
2649
+ headers: requestHeaders
2650
+ });
2651
+ if (!response.ok) {
2652
+ throw new HTTPError(response.status, response.statusText);
2653
+ }
2654
+ const { csrf_token: csrfToken } = await response.json();
2655
+ return csrfToken || null;
2656
+ };
2657
+ /**
2658
+ * Fetches JSON data from a specified URL using the Fetch API.
2659
+ *
2660
+ * @param {string} url - The URL to fetch the JSON data from.
2661
+ * @param {boolean} [requiresCSRF=false] - Indicates whether a CSRF token is required for the request.
2662
+ * If true, the CSRF token will be added to the request headers.
2663
+ * @param {string} [method=DEFAULT_METHOD] - The HTTP method to use for the request (e.g., 'GET', 'POST').
2664
+ * @param {unknown} [body=undefined] - The request body to send, applicable when using methods like 'POST'.
2665
+ *
2666
+ * @returns {Promise<any>} A promise that resolves to the parsed JSON data from the response.
2667
+ *
2668
+ * @throws {HTTPError} Throws an error if the HTTP response status indicates a failure.
2669
+ */ const fetchJSONDataFromURL = async (url, requiresCSRF = false, method = DEFAULT_METHOD, body = undefined)=>{
2670
+ const requestHeaders = new Headers({
2671
+ [CONTENT_TYPE_HEADER]: CONTENT_TYPE_JSON
2672
+ });
2673
+ if (requiresCSRF) {
2674
+ const csrfToken = await getCSRFToken();
2675
+ if (csrfToken) {
2676
+ requestHeaders.set('X-CSRF-Token', csrfToken);
2677
+ }
2678
+ }
2679
+ if (process.env.NODE_ENV === 'development') {
2680
+ const accessToken = cookiesNext.getCookie('credentials_token');
2681
+ if (accessToken) {
2682
+ requestHeaders.set('Authorization', `Bearer ${accessToken}`);
2683
+ }
2684
+ }
2685
+ const response = await fetch(url, {
2686
+ method,
2687
+ headers: requestHeaders,
2688
+ body: method === 'POST' ? JSON.stringify(body) : null
2689
+ });
2690
+ if (!response.ok) {
2691
+ throw new HTTPError(response.status, response.statusText);
2692
+ }
2693
+ return response.json();
2694
+ };
2479
2695
 
2480
2696
  const persistor = reduxPersist.persistStore(coreStore);
2481
2697
  const CoreProvider = ({ children })=>{
@@ -3302,7 +3518,6 @@ exports.GEN3_SOWER_API = GEN3_SOWER_API;
3302
3518
  exports.GEN3_SUBMISSION_API = GEN3_SUBMISSION_API;
3303
3519
  exports.GEN3_WORKSPACE_API = GEN3_WORKSPACE_API;
3304
3520
  exports.HTTPError = HTTPError;
3305
- exports.HTTPErrorMessages = HTTPErrorMessages;
3306
3521
  exports.Modals = Modals;
3307
3522
  exports.PodConditionType = PodConditionType;
3308
3523
  exports.PodStatus = PodStatus;
@@ -3311,7 +3526,6 @@ exports.WorkspaceStatus = WorkspaceStatus;
3311
3526
  exports.clearActiveWorkspaceId = clearActiveWorkspaceId;
3312
3527
  exports.clearCohortFilters = clearCohortFilters;
3313
3528
  exports.clearDataLibrarySelection = clearDataLibrarySelection;
3314
- exports.cohortReducer = cohortReducer;
3315
3529
  exports.convertFilterSetToGqlFilter = convertFilterSetToGqlFilter;
3316
3530
  exports.coreStore = coreStore;
3317
3531
  exports.createAppApiForRTKQ = createAppApiForRTKQ;
@@ -3330,6 +3544,7 @@ exports.extractIndexAndFieldNameFromFullFieldName = extractIndexAndFieldNameFrom
3330
3544
  exports.extractIndexFromFullFieldName = extractIndexFromFullFieldName;
3331
3545
  exports.fetchFence = fetchFence;
3332
3546
  exports.fetchFencePresignedURL = fetchFencePresignedURL;
3547
+ exports.fetchJSONDataFromURL = fetchJSONDataFromURL;
3333
3548
  exports.fetchJson = fetchJson;
3334
3549
  exports.fetchUserState = fetchUserState;
3335
3550
  exports.fieldNameToTitle = fieldNameToTitle;
@@ -3340,6 +3555,7 @@ exports.getNumberOfItemsInDatalist = getNumberOfItemsInDatalist;
3340
3555
  exports.getTimestamp = getTimestamp;
3341
3556
  exports.graphQLAPI = graphQLAPI;
3342
3557
  exports.graphQLWithTags = graphQLWithTags;
3558
+ exports.groupSharedFields = groupSharedFields;
3343
3559
  exports.guppyAPISliceMiddleware = guppyAPISliceMiddleware;
3344
3560
  exports.guppyApi = guppyApi;
3345
3561
  exports.guppyApiReducer = guppyApiReducer;
@@ -3352,6 +3568,7 @@ exports.isAuthenticated = isAuthenticated;
3352
3568
  exports.isCohortItem = isCohortItem;
3353
3569
  exports.isErrorWithMessage = isErrorWithMessage;
3354
3570
  exports.isFetchBaseQueryError = isFetchBaseQueryError;
3571
+ exports.isFetchError = isFetchError;
3355
3572
  exports.isFetchParseError = isFetchParseError;
3356
3573
  exports.isFileItem = isFileItem;
3357
3574
  exports.isFilterEmpty = isFilterEmpty;
@@ -3366,17 +3583,20 @@ exports.isHistogramDataArrayAnEnum = isHistogramDataArrayAnEnum;
3366
3583
  exports.isHistogramDataCollection = isHistogramDataCollection;
3367
3584
  exports.isHistogramRangeData = isHistogramRangeData;
3368
3585
  exports.isHttpStatusError = isHttpStatusError;
3586
+ exports.isIntersection = isIntersection;
3369
3587
  exports.isJSONObject = isJSONObject;
3370
3588
  exports.isJSONValue = isJSONValue;
3371
3589
  exports.isJSONValueArray = isJSONValueArray;
3372
3590
  exports.isNotDefined = isNotDefined;
3373
3591
  exports.isObject = isObject;
3374
3592
  exports.isOperationWithField = isOperationWithField;
3593
+ exports.isOperatorWithFieldAndArrayOfOperands = isOperatorWithFieldAndArrayOfOperands;
3375
3594
  exports.isPending = isPending;
3376
3595
  exports.isProgramUrl = isProgramUrl;
3377
3596
  exports.isRootUrl = isRootUrl;
3378
3597
  exports.isString = isString;
3379
3598
  exports.isTimeGreaterThan = isTimeGreaterThan;
3599
+ exports.isUnion = isUnion;
3380
3600
  exports.isWorkspaceActive = isWorkspaceActive;
3381
3601
  exports.isWorkspaceRunningOrStopping = isWorkspaceRunningOrStopping;
3382
3602
  exports.listifyMethodsFromMapping = listifyMethodsFromMapping;
@@ -3391,9 +3611,12 @@ exports.resetUserState = resetUserState;
3391
3611
  exports.resourcePathFromProjectID = resourcePathFromProjectID;
3392
3612
  exports.selectActiveWorkspaceId = selectActiveWorkspaceId;
3393
3613
  exports.selectActiveWorkspaceStatus = selectActiveWorkspaceStatus;
3614
+ exports.selectAllCohortFiltersCollapsed = selectAllCohortFiltersCollapsed;
3394
3615
  exports.selectAuthzMappingData = selectAuthzMappingData;
3395
3616
  exports.selectCSRFToken = selectCSRFToken;
3396
3617
  exports.selectCSRFTokenData = selectCSRFTokenData;
3618
+ exports.selectCohortFilterCombineMode = selectCohortFilterCombineMode;
3619
+ exports.selectCohortFilterExpanded = selectCohortFilterExpanded;
3397
3620
  exports.selectCohortFilters = selectCohortFilters;
3398
3621
  exports.selectCurrentCohort = selectCurrentCohort;
3399
3622
  exports.selectCurrentCohortId = selectCurrentCohortId;
@@ -3408,6 +3631,9 @@ exports.selectIndexedFilterByName = selectIndexedFilterByName;
3408
3631
  exports.selectPaymodelStatus = selectPaymodelStatus;
3409
3632
  exports.selectRequestedWorkspaceStatus = selectRequestedWorkspaceStatus;
3410
3633
  exports.selectRequestedWorkspaceStatusTimestamp = selectRequestedWorkspaceStatusTimestamp;
3634
+ exports.selectSharedFilters = selectSharedFilters;
3635
+ exports.selectSharedFiltersForFields = selectSharedFiltersForFields;
3636
+ exports.selectShouldShareFilters = selectShouldShareFilters;
3411
3637
  exports.selectUser = selectUser;
3412
3638
  exports.selectUserAuthStatus = selectUserAuthStatus;
3413
3639
  exports.selectUserData = selectUserData;
@@ -3419,13 +3645,18 @@ exports.setActiveWorkspace = setActiveWorkspace;
3419
3645
  exports.setActiveWorkspaceId = setActiveWorkspaceId;
3420
3646
  exports.setActiveWorkspaceStatus = setActiveWorkspaceStatus;
3421
3647
  exports.setCohortFilter = setCohortFilter;
3648
+ exports.setCohortFilterCombineMode = setCohortFilterCombineMode;
3422
3649
  exports.setCohortIndexFilters = setCohortIndexFilters;
3423
3650
  exports.setDRSHostnames = setDRSHostnames;
3424
3651
  exports.setDataLibraryListSelection = setDataLibraryListSelection;
3425
3652
  exports.setRequestedWorkspaceStatus = setRequestedWorkspaceStatus;
3653
+ exports.setSharedFilters = setSharedFilters;
3654
+ exports.setShouldShareFilters = setShouldShareFilters;
3426
3655
  exports.setupCoreStore = setupCoreStore;
3427
3656
  exports.showModal = showModal;
3428
3657
  exports.submissionApi = submissionApi;
3658
+ exports.toggleCohortBuilderAllFilters = toggleCohortBuilderAllFilters;
3659
+ exports.toggleCohortBuilderCategoryFilter = toggleCohortBuilderCategoryFilter;
3429
3660
  exports.trimFirstFieldNameToTitle = trimFirstFieldNameToTitle;
3430
3661
  exports.updateCohortFilter = updateCohortFilter;
3431
3662
  exports.useAddDataLibraryListMutation = useAddDataLibraryListMutation;
@@ -3444,6 +3675,7 @@ exports.useGetAISearchVersionQuery = useGetAISearchVersionQuery;
3444
3675
  exports.useGetAccessibleDataQuery = useGetAccessibleDataQuery;
3445
3676
  exports.useGetActivePayModelQuery = useGetActivePayModelQuery;
3446
3677
  exports.useGetAggMDSQuery = useGetAggMDSQuery;
3678
+ exports.useGetAggsNoFilterSelfQuery = useGetAggsNoFilterSelfQuery;
3447
3679
  exports.useGetAggsQuery = useGetAggsQuery;
3448
3680
  exports.useGetAllFieldsForTypeQuery = useGetAllFieldsForTypeQuery;
3449
3681
  exports.useGetArrayTypes = useGetArrayTypes;
@@ -3469,6 +3701,7 @@ exports.useGetMetadataByIdQuery = useGetMetadataByIdQuery;
3469
3701
  exports.useGetProjectsDetailsQuery = useGetProjectsDetailsQuery;
3470
3702
  exports.useGetProjectsQuery = useGetProjectsQuery;
3471
3703
  exports.useGetRawDataAndTotalCountsQuery = useGetRawDataAndTotalCountsQuery;
3704
+ exports.useGetSharedFieldsForIndexQuery = useGetSharedFieldsForIndexQuery;
3472
3705
  exports.useGetSowerJobListQuery = useGetSowerJobListQuery;
3473
3706
  exports.useGetSowerJobStatusQuery = useGetSowerJobStatusQuery;
3474
3707
  exports.useGetSowerOutputQuery = useGetSowerOutputQuery;