@gen3/core 0.10.94 → 0.10.97

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 (82) hide show
  1. package/dist/cjs/index.js +631 -126
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/dts/constants.d.ts +1 -0
  4. package/dist/dts/constants.d.ts.map +1 -1
  5. package/dist/dts/features/authz/authzMappingSlice.d.ts +463 -31
  6. package/dist/dts/features/authz/authzMappingSlice.d.ts.map +1 -1
  7. package/dist/dts/features/authz/index.d.ts +2 -2
  8. package/dist/dts/features/authz/index.d.ts.map +1 -1
  9. package/dist/dts/features/authz/types.d.ts +17 -0
  10. package/dist/dts/features/authz/types.d.ts.map +1 -1
  11. package/dist/dts/features/cohort/cohortSlice.d.ts +152 -77
  12. package/dist/dts/features/cohort/cohortSlice.d.ts.map +1 -1
  13. package/dist/dts/features/cohort/index.d.ts +2 -2
  14. package/dist/dts/features/cohort/index.d.ts.map +1 -1
  15. package/dist/dts/features/cohort/reducers.d.ts +2 -2
  16. package/dist/dts/features/cohort/utils.d.ts +2 -0
  17. package/dist/dts/features/cohort/utils.d.ts.map +1 -0
  18. package/dist/dts/features/dataLibrary/index.d.ts +1 -1
  19. package/dist/dts/features/dataLibrary/index.d.ts.map +1 -1
  20. package/dist/dts/features/dataLibrary/storage/types.d.ts +1 -5
  21. package/dist/dts/features/dataLibrary/storage/types.d.ts.map +1 -1
  22. package/dist/dts/features/dataLibrary/useDataLibrary.d.ts +1 -1
  23. package/dist/dts/features/dataLibrary/useDataLibrary.d.ts.map +1 -1
  24. package/dist/dts/features/fence/utils.d.ts.map +1 -1
  25. package/dist/dts/features/filters/filters.d.ts +17 -0
  26. package/dist/dts/features/filters/filters.d.ts.map +1 -1
  27. package/dist/dts/features/filters/index.d.ts +2 -2
  28. package/dist/dts/features/filters/index.d.ts.map +1 -1
  29. package/dist/dts/features/filters/tests/filters.unit.test.d.ts +2 -0
  30. package/dist/dts/features/filters/tests/filters.unit.test.d.ts.map +1 -0
  31. package/dist/dts/features/filters/types.d.ts +4 -1
  32. package/dist/dts/features/filters/types.d.ts.map +1 -1
  33. package/dist/dts/features/gen3/gen3Api.d.ts.map +1 -1
  34. package/dist/dts/features/gen3Apps/Gen3AppRTKQ.d.ts +4 -8
  35. package/dist/dts/features/gen3Apps/Gen3AppRTKQ.d.ts.map +1 -1
  36. package/dist/dts/features/guppy/guppySlice.d.ts +189 -2
  37. package/dist/dts/features/guppy/guppySlice.d.ts.map +1 -1
  38. package/dist/dts/features/guppy/index.d.ts +2 -0
  39. package/dist/dts/features/guppy/index.d.ts.map +1 -1
  40. package/dist/dts/features/guppy/processing.d.ts +20 -0
  41. package/dist/dts/features/guppy/processing.d.ts.map +1 -0
  42. package/dist/dts/features/guppy/tests/processing.unit.test.d.ts +2 -0
  43. package/dist/dts/features/guppy/tests/processing.unit.test.d.ts.map +1 -0
  44. package/dist/dts/features/requestor/index.d.ts +5 -0
  45. package/dist/dts/features/requestor/index.d.ts.map +1 -0
  46. package/dist/dts/features/requestor/remoteSupport/index.d.ts +5 -0
  47. package/dist/dts/features/requestor/remoteSupport/index.d.ts.map +1 -0
  48. package/dist/dts/features/requestor/remoteSupport/registerDefaultRemoteSupport.d.ts +2 -0
  49. package/dist/dts/features/requestor/remoteSupport/registerDefaultRemoteSupport.d.ts.map +1 -0
  50. package/dist/dts/features/requestor/remoteSupport/registeredRemoteSupportServices.d.ts +48 -0
  51. package/dist/dts/features/requestor/remoteSupport/registeredRemoteSupportServices.d.ts.map +1 -0
  52. package/dist/dts/features/requestor/remoteSupport/types.d.ts +12 -0
  53. package/dist/dts/features/requestor/remoteSupport/types.d.ts.map +1 -0
  54. package/dist/dts/features/requestor/remoteSupport/zenDesk.d.ts +5 -0
  55. package/dist/dts/features/requestor/remoteSupport/zenDesk.d.ts.map +1 -0
  56. package/dist/dts/features/requestor/requestorSlice.d.ts +870 -0
  57. package/dist/dts/features/requestor/requestorSlice.d.ts.map +1 -0
  58. package/dist/dts/features/user/index.d.ts +2 -2
  59. package/dist/dts/features/user/index.d.ts.map +1 -1
  60. package/dist/dts/features/user/userSliceRTK.d.ts +171 -4
  61. package/dist/dts/features/user/userSliceRTK.d.ts.map +1 -1
  62. package/dist/dts/hooks.d.ts +2 -2
  63. package/dist/dts/index.d.ts +1 -0
  64. package/dist/dts/index.d.ts.map +1 -1
  65. package/dist/dts/reducers.d.ts +3 -3
  66. package/dist/dts/store.d.ts +4 -4
  67. package/dist/dts/types/index.d.ts +17 -6
  68. package/dist/dts/types/index.d.ts.map +1 -1
  69. package/dist/dts/utils/caseConversion.d.ts +3 -0
  70. package/dist/dts/utils/caseConversion.d.ts.map +1 -0
  71. package/dist/dts/utils/extractvalues.d.ts +1 -4
  72. package/dist/dts/utils/extractvalues.d.ts.map +1 -1
  73. package/dist/dts/utils/fetch.d.ts +1 -1
  74. package/dist/dts/utils/fetch.d.ts.map +1 -1
  75. package/dist/dts/utils/logger.d.ts +6 -0
  76. package/dist/dts/utils/logger.d.ts.map +1 -0
  77. package/dist/dts/utils/test/caseConversion.unit.test.d.ts +2 -0
  78. package/dist/dts/utils/test/caseConversion.unit.test.d.ts.map +1 -0
  79. package/dist/esm/index.js +603 -128
  80. package/dist/esm/index.js.map +1 -1
  81. package/dist/index.d.ts +8359 -6542
  82. package/package.json +2 -2
package/dist/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createSelector, createAsyncThunk, createSlice, combineReducers, configureStore, nanoid } from '@reduxjs/toolkit';
1
+ import { createSelector, createAsyncThunk, createSlice, createEntityAdapter, nanoid, combineReducers, configureStore } from '@reduxjs/toolkit';
2
2
  import { createApi, fetchBaseQuery, buildCreateApi, coreModule, reactHooksModule } from '@reduxjs/toolkit/query/react';
3
3
  import { getCookie } from 'cookies-next';
4
4
  import { QueryStatus, setupListeners } from '@reduxjs/toolkit/query';
@@ -15,9 +15,9 @@ import { openDB } from 'idb';
15
15
  import { v5 } from 'uuid';
16
16
  import { CookiesProvider } from 'react-cookie';
17
17
  import useSWR from 'swr';
18
- import { JSONPath } from 'jsonpath-plus';
19
18
  import { flatten } from 'flat';
20
19
  import Papa from 'papaparse';
20
+ import { JSONPath } from 'jsonpath-plus';
21
21
  import Queue from 'queue';
22
22
 
23
23
  const GEN3_COMMONS_NAME = process.env.NEXT_PUBLIC_GEN3_COMMONS_NAME || 'gen3';
@@ -40,6 +40,7 @@ const GEN3_DATA_LIBRARY_API = process.env.NEXT_PUBLIC_GEN3_DATA_LIBRARY_API || `
40
40
  const GEN3_CROSSWALK_API = process.env.NEXT_PUBLIC_GEN3_CROSSWALK_API || `${GEN3_API}/mds`;
41
41
  const GEN3_SOWER_API = process.env.NEXT_PUBLIC_GEN3_SOWER_API || `${GEN3_API}/jobs`;
42
42
  const GEN3_MANIFEST_API = process.env.NEXT_PUBLIC_GEN3_MANIFEST_API || `${GEN3_API}/manifests`;
43
+ const GEN3_REQUESTOR_API = process.env.NEXT_PUBLIC_GEN3_REQUESTOR_API || `${GEN3_API}/requestor`;
43
44
  var Accessibility = /*#__PURE__*/ function(Accessibility) {
44
45
  Accessibility["ACCESSIBLE"] = "accessible";
45
46
  Accessibility["UNACCESSIBLE"] = "unaccessible";
@@ -76,6 +77,7 @@ const isFetchError = (obj)=>{
76
77
  */ const fetchFence = async ({ endpoint, headers, body = {}, method = 'GET', isJSON = true })=>{
77
78
  const res = await fetch(`${GEN3_FENCE_API}${endpoint}`, {
78
79
  method: method,
80
+ credentials: 'include',
79
81
  headers: headers,
80
82
  body: 'POST' === method ? JSON.stringify(body) : null
81
83
  });
@@ -168,6 +170,10 @@ const userAuthApi = createApi({
168
170
  return {
169
171
  error: error
170
172
  };
173
+ } else {
174
+ return {
175
+ error: 'Unknown Error'
176
+ };
171
177
  }
172
178
  }
173
179
  return {
@@ -180,7 +186,7 @@ const userAuthApi = createApi({
180
186
  const EMPTY_USER = {
181
187
  username: undefined
182
188
  };
183
- const { useFetchUserDetailsQuery, useLazyFetchUserDetailsQuery, useGetCSRFQuery } = userAuthApi;
189
+ const { useFetchUserDetailsQuery, useLazyFetchUserDetailsQuery, useGetCSRFQuery, useLazyGetCSRFQuery } = userAuthApi;
184
190
  const userAuthApiMiddleware = userAuthApi.middleware;
185
191
  const userAuthApiReducerPath = userAuthApi.reducerPath;
186
192
  const userAuthApiReducer = userAuthApi.reducer;
@@ -225,6 +231,9 @@ const selectHeadersWithCSRFToken = createSelector([
225
231
  }
226
232
  if (csrfToken) headers.set('X-CSRF-Token', csrfToken);
227
233
  return headers;
234
+ },
235
+ validateStatus: (response)=>{
236
+ return response.status >= 200 && response.status < 300;
228
237
  }
229
238
  }),
230
239
  endpoints: ()=>({})
@@ -396,7 +405,7 @@ const useCoreDispatch = useDispatch.withTypes();
396
405
  });
397
406
  const isAuthenticated = (loginStatus)=>loginStatus === 'authenticated';
398
407
  const isPending = (loginStatus)=>loginStatus === 'pending';
399
- const initialState$7 = {
408
+ const initialState$8 = {
400
409
  status: 'uninitialized',
401
410
  loginStatus: 'unauthenticated',
402
411
  error: undefined
@@ -407,9 +416,9 @@ const initialState$7 = {
407
416
  * @returns: status messages wrapped around fetchUserState response dict
408
417
  */ const slice$4 = createSlice({
409
418
  name: 'fence/user',
410
- initialState: initialState$7,
419
+ initialState: initialState$8,
411
420
  reducers: {
412
- resetUserState: ()=>initialState$7
421
+ resetUserState: ()=>initialState$8
413
422
  },
414
423
  extraReducers: (builder)=>{
415
424
  builder.addCase(fetchUserState.fulfilled, (_, action)=>{
@@ -551,11 +560,11 @@ const { useGetExternalLoginsQuery, useLazyGetExternalLoginsQuery, useLazyIsExter
551
560
  }
552
561
  };
553
562
 
554
- const initialState$6 = {};
563
+ const initialState$7 = {};
555
564
  // TODO: document what this does
556
565
  const slice$3 = createSlice({
557
566
  name: 'drsResolver',
558
- initialState: initialState$6,
567
+ initialState: initialState$7,
559
568
  reducers: {
560
569
  setDRSHostnames: (_state, action)=>{
561
570
  return action.payload;
@@ -576,12 +585,12 @@ const lookupGen3App = (id)=>{
576
585
  return REGISTRY[id];
577
586
  };
578
587
 
579
- const initialState$5 = {
588
+ const initialState$6 = {
580
589
  gen3Apps: {}
581
590
  };
582
591
  const slice$2 = createSlice({
583
592
  name: 'gen3Apps',
584
- initialState: initialState$5,
593
+ initialState: initialState$6,
585
594
  reducers: {
586
595
  addGen3AppMetadata: (state, action)=>{
587
596
  const { name, requiredEntityTypes } = action.payload;
@@ -612,13 +621,13 @@ const selectGen3AppByName = (appName)=>lookupGen3App(appName); // TODO: memoize
612
621
  Modals["GeneralErrorModal"] = "GeneralErrorModal";
613
622
  return Modals;
614
623
  }({});
615
- const initialState$4 = {
624
+ const initialState$5 = {
616
625
  currentModal: null
617
626
  };
618
627
  //Creates a modal slice for tracking showModal and hideModal state.
619
628
  const slice$1 = createSlice({
620
629
  name: 'modals',
621
- initialState: initialState$4,
630
+ initialState: initialState$5,
622
631
  reducers: {
623
632
  showModal: (state, action)=>{
624
633
  state.currentModal = action.payload.modal;
@@ -688,7 +697,7 @@ const isTimeGreaterThan = (startTime, minutes)=>{
688
697
  };
689
698
 
690
699
  const NO_WORKSPACE_ID = 'none';
691
- const initialState$3 = {
700
+ const initialState$4 = {
692
701
  id: NO_WORKSPACE_ID,
693
702
  status: WorkspaceStatus.NotFound,
694
703
  requestedStatus: RequestedWorkspaceStatus.Unset,
@@ -696,7 +705,7 @@ const initialState$3 = {
696
705
  };
697
706
  const slice = createSlice({
698
707
  name: 'ActiveWorkspace',
699
- initialState: initialState$3,
708
+ initialState: initialState$4,
700
709
  reducers: {
701
710
  setActiveWorkspaceId: (state, action)=>{
702
711
  state = {
@@ -786,119 +795,260 @@ const guppyAPISliceMiddleware = guppyApi.middleware;
786
795
  const guppyApiSliceReducerPath = guppyApi.reducerPath;
787
796
  const guppyApiReducer = guppyApi.reducer;
788
797
 
789
- const EmptyCohort = {
790
- id: 'default',
791
- name: 'Filters',
792
- filters: {},
793
- modified_datetime: new Date().toISOString()
794
- };
795
- const initialCohortState = {
796
- cohort: {
797
- ...EmptyCohort
798
- }
798
+ /**
799
+ * Cohorts in Gen3 are defined as a set of filters for each index in the data.
800
+ * This means one cohort id defined for all "tabs" in CohortBuilder (explorer)
801
+ * Switching a cohort is means that all the cohorts for the index changes.
802
+ */ const UNSAVED_COHORT_NAME = 'Unsaved_Cohort';
803
+ const NULL_COHORT_ID = 'null_cohort_id';
804
+ const newCohort = ({ filters = {}, customName })=>{
805
+ const ts = new Date();
806
+ const newName = customName;
807
+ const newId = createCohortId();
808
+ return {
809
+ name: newName,
810
+ id: newId,
811
+ filters: filters ?? {},
812
+ modified: false,
813
+ saved: false,
814
+ modified_datetime: ts.toISOString()
815
+ };
799
816
  };
800
- // TODO: start using this adapter
801
- /*
802
- const cohortsAdapter = createEntityAdapter<Cohort>({
803
- sortComparer: (a, b) => {
804
- if (a.modified_datetime <= b.modified_datetime) return 1;
805
- else return -1;
806
- },
817
+ const createCohortId = ()=>nanoid();
818
+ const cohortsAdapter = createEntityAdapter({
819
+ sortComparer: (a, b)=>{
820
+ if (a.modified_datetime <= b.modified_datetime) return 1;
821
+ else return -1;
822
+ },
823
+ selectId: (cohort)=>cohort.id
824
+ });
825
+ // Create an initial unsaved cohort
826
+ const initialCohort = newCohort({
827
+ customName: UNSAVED_COHORT_NAME
807
828
  });
808
- */ /**
829
+ const emptyInitialState = cohortsAdapter.getInitialState({
830
+ currentCohort: initialCohort.id,
831
+ message: undefined
832
+ });
833
+ // Set the initial cohort in the adapter state
834
+ const initialState$3 = cohortsAdapter.setOne(emptyInitialState, initialCohort);
835
+ const getCurrentCohort = (state)=>{
836
+ if (state.currentCohort) {
837
+ return state.currentCohort;
838
+ }
839
+ return NULL_COHORT_ID;
840
+ };
841
+ /**
809
842
  * Redux slice for cohort filters
810
843
  */ const cohortSlice = createSlice({
811
844
  name: 'cohort',
812
- initialState: initialCohortState,
845
+ initialState: initialState$3,
813
846
  reducers: {
847
+ addNewDefaultUnsavedCohort: (state)=>{
848
+ const cohort = newCohort({
849
+ customName: UNSAVED_COHORT_NAME
850
+ });
851
+ cohortsAdapter.addOne(state, cohort);
852
+ state.currentCohort = cohort.id;
853
+ state.message = [
854
+ `newCohort|${cohort.name}|${cohort.id}`
855
+ ];
856
+ },
857
+ updateCohortName: (state, action)=>{
858
+ cohortsAdapter.updateOne(state, {
859
+ id: getCurrentCohort(state),
860
+ changes: {
861
+ name: action.payload,
862
+ modified: true,
863
+ modified_datetime: new Date().toISOString()
864
+ }
865
+ });
866
+ },
867
+ removeCohort: (state, action)=>{
868
+ const removedCohort = state.entities[action?.payload?.id || getCurrentCohort(state)];
869
+ cohortsAdapter.removeOne(state, action?.payload?.id || getCurrentCohort(state));
870
+ if (action?.payload.shouldShowMessage) {
871
+ state.message = [
872
+ `deleteCohort|${removedCohort?.name}|${state.currentCohort}`
873
+ ];
874
+ }
875
+ },
814
876
  // adds a filter to the cohort filter set at the given index
815
877
  updateCohortFilter: (state, action)=>{
816
878
  const { index, field, filter } = action.payload;
817
- return {
818
- cohort: {
819
- ...state.cohort,
879
+ const currentCohortId = getCurrentCohort(state);
880
+ if (!state.entities[currentCohortId]) {
881
+ return;
882
+ }
883
+ cohortsAdapter.updateOne(state, {
884
+ id: currentCohortId,
885
+ changes: {
820
886
  filters: {
821
- ...state.cohort.filters,
887
+ ...state.entities[currentCohortId].filters,
822
888
  [index]: {
823
- mode: state.cohort.filters?.[index]?.mode ?? 'and',
889
+ mode: state.entities[currentCohortId]?.filters[index]?.mode ?? 'and',
824
890
  root: {
825
- ...state.cohort.filters?.[index]?.root ?? {},
891
+ ...state.entities[currentCohortId]?.filters[index]?.root ?? {},
826
892
  [field]: filter
827
893
  }
828
894
  }
829
- }
895
+ },
896
+ modified: true,
897
+ modified_datetime: new Date().toISOString()
830
898
  }
831
- };
899
+ });
832
900
  },
833
901
  setCohortFilter: (state, action)=>{
834
902
  const { index, filters } = action.payload;
835
- return {
836
- cohort: {
837
- ...state.cohort,
903
+ const currentCohortId = getCurrentCohort(state);
904
+ if (!state.entities[currentCohortId]) {
905
+ console.error(`no cohort with id=${currentCohortId} defined`);
906
+ return;
907
+ }
908
+ cohortsAdapter.updateOne(state, {
909
+ id: currentCohortId,
910
+ changes: {
838
911
  filters: {
839
- ...state.cohort.filters,
912
+ ...state.entities[currentCohortId].filters,
840
913
  [index]: filters
841
- }
914
+ },
915
+ modified: true,
916
+ modified_datetime: new Date().toISOString()
842
917
  }
843
- };
918
+ });
844
919
  },
845
920
  setCohortIndexFilters: (state, action)=>{
846
- return {
847
- cohort: {
848
- ...state.cohort,
849
- filters: {
850
- ...action.payload.filters
851
- }
921
+ const currentCohortId = getCurrentCohort(state);
922
+ if (!state.entities[currentCohortId]) {
923
+ console.error(`no cohort with id=${currentCohortId} defined`);
924
+ return;
925
+ }
926
+ cohortsAdapter.updateOne(state, {
927
+ id: currentCohortId,
928
+ changes: {
929
+ filters: action.payload.filters,
930
+ modified: true,
931
+ modified_datetime: new Date().toISOString()
852
932
  }
853
- };
933
+ });
854
934
  },
855
935
  // removes a filter to the cohort filter set at the given index
856
936
  removeCohortFilter: (state, action)=>{
857
937
  const { index, field } = action.payload;
858
- const filters = state.cohort?.filters?.[index]?.root;
938
+ const currentCohortId = getCurrentCohort(state);
939
+ if (!state.entities[currentCohortId]) {
940
+ console.error(`no cohort with id=${currentCohortId} defined`);
941
+ return;
942
+ }
943
+ const filters = state.entities[currentCohortId]?.filters[index]?.root;
859
944
  if (!filters) {
860
945
  return;
861
946
  }
862
947
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
863
948
  const { [field]: _a, ...updated } = filters;
864
- return {
865
- cohort: {
866
- ...state.cohort,
949
+ cohortsAdapter.updateOne(state, {
950
+ id: currentCohortId,
951
+ changes: {
867
952
  filters: {
868
- ...state.cohort.filters,
953
+ ...state.entities[currentCohortId]?.filters,
869
954
  [index]: {
870
- mode: state.cohort.filters[index].mode,
955
+ mode: state.entities[currentCohortId].filters[index].mode,
871
956
  root: updated
872
957
  }
873
- }
958
+ },
959
+ modified: true,
960
+ modified_datetime: new Date().toISOString()
874
961
  }
875
- };
962
+ });
876
963
  },
877
964
  // removes all filters from the cohort filter set at the given index
878
965
  clearCohortFilters: (state, action)=>{
879
966
  const { index } = action.payload;
880
- return {
881
- cohort: {
882
- ...state.cohort,
967
+ const currentCohortId = getCurrentCohort(state);
968
+ if (!state.entities[currentCohortId]) {
969
+ console.error(`no cohort with id=${currentCohortId} defined`);
970
+ return;
971
+ }
972
+ const filters = state.entities[currentCohortId]?.filters[index]?.root;
973
+ if (!filters) {
974
+ return;
975
+ }
976
+ cohortsAdapter.updateOne(state, {
977
+ id: currentCohortId,
978
+ changes: {
883
979
  filters: {
884
- ...state.cohort.filters,
980
+ ...state.entities[currentCohortId]?.filters,
885
981
  [index]: {
886
- // empty filter set
887
982
  mode: 'and',
888
983
  root: {}
889
984
  }
890
- }
985
+ },
986
+ modified: true,
987
+ modified_datetime: new Date().toISOString()
891
988
  }
892
- };
989
+ });
990
+ },
991
+ discardCohortChanges: (state, action)=>{
992
+ const { index, id, filters } = action.payload;
993
+ const cohortId = id ?? getCurrentCohort(state);
994
+ cohortsAdapter.updateOne(state, {
995
+ id: cohortId,
996
+ changes: {
997
+ filters: {
998
+ ...state.entities[cohortId].filters,
999
+ [index]: filters || {
1000
+ mode: 'and',
1001
+ root: {}
1002
+ }
1003
+ },
1004
+ modified: false,
1005
+ modified_datetime: new Date().toISOString()
1006
+ }
1007
+ });
1008
+ },
1009
+ setCurrentCohortId: (state, action)=>{
1010
+ state.currentCohort = action.payload;
1011
+ },
1012
+ /** @hidden */ setCohortList: (state, action)=>{
1013
+ if (!action.payload) {
1014
+ cohortsAdapter.removeMany(state, state.ids);
1015
+ } else {
1016
+ cohortsAdapter.upsertMany(state, [
1017
+ ...action.payload
1018
+ ]);
1019
+ }
893
1020
  }
894
1021
  }
895
1022
  });
1023
+ /**
1024
+ * Returns the selectors for the cohorts EntityAdapter
1025
+ * @param state - the CoreState
1026
+ *
1027
+ * @hidden
1028
+ */ const cohortSelectors = cohortsAdapter.getSelectors((state)=>state.cohorts.cohort);
1029
+ /**
1030
+ * Returns an array of all the cohorts
1031
+ * @param state - the CoreState
1032
+ * @category Cohort
1033
+ * @category Selectors
1034
+ */ const selectAllCohorts = (state)=>cohortSelectors.selectEntities(state);
1035
+ const getCurrentCohortFromCoreState = (state)=>{
1036
+ if (state.cohorts.cohort.currentCohort) {
1037
+ return state.cohorts.cohort.currentCohort;
1038
+ }
1039
+ return NULL_COHORT_ID;
1040
+ };
896
1041
  // Filter actions: addFilter, removeFilter, updateFilter
897
- const { updateCohortFilter, setCohortFilter, setCohortIndexFilters, removeCohortFilter, clearCohortFilters } = cohortSlice.actions;
898
- const selectCohortFilters = (state)=>state.cohorts.cohort.cohort.filters;
899
- const selectCurrentCohortId = (state)=>state.cohorts.cohort.cohort.id;
900
- const selectCurrentCohort = (state)=>state.cohorts.cohort.cohort;
901
- const selectCurrentCohortName = (state)=>state.cohorts.cohort.cohort.name;
1042
+ const { updateCohortFilter, setCohortFilter, setCohortIndexFilters, removeCohortFilter, clearCohortFilters, removeCohort, discardCohortChanges, addNewDefaultUnsavedCohort, setCurrentCohortId, setCohortList } = cohortSlice.actions;
1043
+ const selectCohortFilters = (state)=>{
1044
+ const currentCohortId = getCurrentCohortFromCoreState(state);
1045
+ return state.cohorts.cohort.entities[currentCohortId]?.filters;
1046
+ };
1047
+ const selectCurrentCohortId = (state)=>{
1048
+ return getCurrentCohort(state.cohorts.cohort);
1049
+ };
1050
+ const selectCurrentCohort = (state)=>cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
1051
+ const selectCurrentCohortName = (state)=>cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state)).name;
902
1052
  /**
903
1053
  * Select a filter by its name from the current cohort. If the filter is not found
904
1054
  * returns undefined.
@@ -906,7 +1056,40 @@ const selectCurrentCohortName = (state)=>state.cohorts.cohort.cohort.name;
906
1056
  * @param index which cohort index to select from
907
1057
  * @param name name of the filter to select
908
1058
  */ const selectIndexedFilterByName = (state, index, name)=>{
909
- return state.cohorts.cohort.cohort.filters[index]?.root[name];
1059
+ return cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state)).filters[index]?.root[name];
1060
+ };
1061
+ /**
1062
+ * a thunk to optionally create a caseSet when switching cohorts.
1063
+ * Note the assumption if the caseset member has ids then the caseset has previously been created.
1064
+ */ const setActiveCohort = (cohortId)=>async (dispatch /* getState */ )=>{
1065
+ dispatch(setCurrentCohortId(cohortId));
1066
+ };
1067
+ /**
1068
+ * Returns all the cohorts in the state
1069
+ * @param state - the CoreState
1070
+ *
1071
+ * @category Cohort
1072
+ * @category Selectors
1073
+ */ const selectAvailableCohorts = (state)=>cohortSelectors.selectAll(state);
1074
+ /**
1075
+ * Returns if the current cohort is modified
1076
+ * @param state - the CoreState
1077
+ * @category Cohort
1078
+ * @category Selectors
1079
+ * @hidden
1080
+ */ const selectCurrentCohortModified = (state)=>{
1081
+ const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
1082
+ return cohort?.modified;
1083
+ };
1084
+ /**
1085
+ * Returns if the current cohort has been saved
1086
+ * @param state - the CoreState
1087
+ * @category Cohort
1088
+ * @category Selectors
1089
+ * @hidden
1090
+ */ const selectCurrentCohortSaved = (state)=>{
1091
+ const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
1092
+ return cohort?.saved;
910
1093
  };
911
1094
  const EmptyFilterSet = {
912
1095
  mode: 'and',
@@ -918,8 +1101,23 @@ const EmptyFilterSet = {
918
1101
  * @param state - Core
919
1102
  * @param index which cohort index to select from
920
1103
  */ const selectIndexFilters = (state, index)=>{
921
- return state.cohorts.cohort.cohort.filters?.[index] ?? EmptyFilterSet; // TODO: check if this is undefined
1104
+ const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
1105
+ if (!cohort) {
1106
+ console.error('No Cohort Defined');
1107
+ }
1108
+ return cohort?.filters?.[index] ?? EmptyFilterSet;
922
1109
  };
1110
+ const setActiveCohortList = (cohorts)=>async (dispatch, getState)=>{
1111
+ // set the list of all cohorts
1112
+ if (cohorts) {
1113
+ dispatch(setCohortList(cohorts));
1114
+ return;
1115
+ }
1116
+ const availableCohorts = selectAllCohorts(getState());
1117
+ if (Object.keys(availableCohorts).length === 0) {
1118
+ dispatch(addNewDefaultUnsavedCohort());
1119
+ }
1120
+ };
923
1121
  const cohortReducer = cohortSlice.reducer;
924
1122
 
925
1123
  const initialState$2 = {};
@@ -1038,7 +1236,7 @@ const persistConfig = {
1038
1236
  version: 1,
1039
1237
  storage,
1040
1238
  whitelist: [
1041
- 'cohort',
1239
+ 'cohorts',
1042
1240
  'activeWorkspace'
1043
1241
  ]
1044
1242
  };
@@ -1278,13 +1476,13 @@ const fetchFencePresignedURL = async ({ guid, method = 'GET', onAbort = ()=>null
1278
1476
  } : {}
1279
1477
  });
1280
1478
  if (!response.ok) {
1281
- throw new HTTPError(response.status, response.statusText);
1479
+ throw new HTTPError(response.status, response.statusText, response.text());
1282
1480
  }
1283
1481
  if (response.status === 204) {
1284
1482
  // no content so return null
1285
1483
  return null;
1286
1484
  }
1287
- return response.json();
1485
+ return await response.json();
1288
1486
  };
1289
1487
 
1290
1488
  const queryWTSFederatedLoginStatus = async (signal)=>{
@@ -1597,19 +1795,42 @@ const CoreProvider = ({ children })=>{
1597
1795
  // Add more endpoints here
1598
1796
  const { useAskQuestionMutation, useGetAISearchStatusQuery, useGetAISearchVersionQuery } = aiSearchApi;
1599
1797
 
1798
+ const TAGS$1 = 'authz';
1799
+ const authzTags = gen3Api.enhanceEndpoints({
1800
+ addTagTypes: [
1801
+ TAGS$1
1802
+ ]
1803
+ });
1600
1804
  /**
1601
1805
  * Creates the authzApi for checking arborist permissions for a selected user
1602
1806
  * @see https://petstore.swagger.io/?url=https://raw.githubusercontent.com/uc-cdis/arborist/master/docs/openapi.yaml#/auth/get_auth_mapping
1603
1807
  * @see https://github.com/uc-cdis/arborist/blob/master/docs/relationships.simplified.png
1604
1808
  * @returns: An arborist response dict of user permissions {method, service} for each resource path.
1605
- */ const authzApi = gen3Api.injectEndpoints({
1809
+ */ const authzApi = authzTags.injectEndpoints({
1606
1810
  endpoints: (builder)=>({
1607
1811
  getAuthzMappings: builder.query({
1608
1812
  query: ()=>`${GEN3_AUTHZ_API}/mapping`
1813
+ }),
1814
+ getAuthzResources: builder.query({
1815
+ query: ()=>({
1816
+ url: `${GEN3_AUTHZ_API}/resources`,
1817
+ method: 'GET'
1818
+ })
1819
+ }),
1820
+ createAuthzResource: builder.mutation({
1821
+ query: (request)=>({
1822
+ // url: `${GEN3_AUTHZ_API}/resources/${request.resourcePath}${request?.path ? `&p=${request.path}` : ''}`,
1823
+ url: `${GEN3_AUTHZ_API}/resources`,
1824
+ method: 'POST',
1825
+ body: request.data
1826
+ }),
1827
+ invalidatesTags: [
1828
+ TAGS$1
1829
+ ]
1609
1830
  })
1610
1831
  })
1611
1832
  });
1612
- const { useGetAuthzMappingsQuery, useLazyGetAuthzMappingsQuery } = authzApi;
1833
+ const { useGetAuthzMappingsQuery, useLazyGetAuthzMappingsQuery, useGetAuthzResourcesQuery, useLazyGetAuthzResourcesQuery, useCreateAuthzResourceMutation } = authzApi;
1613
1834
  const selectAuthzMapping = authzApi.endpoints.getAuthzMappings.select();
1614
1835
  const selectAuthzMappingData = createSelector(selectAuthzMapping, (authzMapping)=>authzMapping?.data ?? {
1615
1836
  mappings: []
@@ -2727,6 +2948,7 @@ const handleOperation = (handler, op)=>{
2727
2948
  case 'nested':
2728
2949
  return handler.handleNestedFilter(op);
2729
2950
  case 'in':
2951
+ case 'includes':
2730
2952
  return handler.handleIncludes(op);
2731
2953
  case 'excludeifany':
2732
2954
  return handler.handleExcludeIfAny(op);
@@ -2881,6 +3103,9 @@ function isUnion(value) {
2881
3103
  function isIntersection(value) {
2882
3104
  return typeof value === 'object' && value !== null && value.operator === 'and' && Array.isArray(value.operands);
2883
3105
  }
3106
+ const isOperandsType = (operation)=>{
3107
+ return operation?.operands !== undefined;
3108
+ };
2884
3109
 
2885
3110
  const FieldNameOverrides = {};
2886
3111
  const COMMON_PREPOSITIONS = [
@@ -3066,9 +3291,11 @@ const createGen3AppWithOwnStore = (options)=>{
3066
3291
  return Gen3AppWrapper;
3067
3292
  };
3068
3293
 
3069
- const createAppApiForRTKQ = (reducerPath, baseQuery)=>{
3294
+ const createAppApiForRTKQ = (reducerPath, name, version, additionalReducers, baseQuery)=>{
3295
+ const nameVersion = `${name}::${version}`;
3296
+ const id = v5(nameVersion, GEN3_APP_NAMESPACE);
3070
3297
  const appContext = React.createContext(null);
3071
- const useAppSelector = useSelector.withTypes();
3298
+ const useAppSelector = createSelectorHook(appContext);
3072
3299
  const useAppDispatch = createDispatchHook(appContext);
3073
3300
  const useAppStore = createStoreHook(appContext);
3074
3301
  const appCreateApi = buildCreateApi(coreModule(), reactHooksModule({
@@ -3084,13 +3311,12 @@ const createAppApiForRTKQ = (reducerPath, baseQuery)=>{
3084
3311
  baseUrl: `${GEN3_API}`,
3085
3312
  prepareHeaders: (headers)=>{
3086
3313
  headers.set('Content-Type', 'application/json');
3087
- let accessToken = undefined;
3088
3314
  if (process.env.NODE_ENV === 'development') {
3089
3315
  // NOTE: This cookie can only be accessed from the client side
3090
3316
  // in development mode. Otherwise, the cookie is set as httpOnly
3091
- accessToken = getCookie('credentials_token');
3317
+ const accessToken = getCookie('credentials_token');
3318
+ if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`);
3092
3319
  }
3093
- if (accessToken) headers.set('Authorization', `Bearer ${accessToken}`);
3094
3320
  return headers;
3095
3321
  }
3096
3322
  }),
@@ -3098,8 +3324,12 @@ const createAppApiForRTKQ = (reducerPath, baseQuery)=>{
3098
3324
  });
3099
3325
  const appMiddleware = appRTKQApi.middleware;
3100
3326
  const appStore = configureStore({
3327
+ devTools: {
3328
+ name: `${nameVersion}::${id}`
3329
+ },
3101
3330
  reducer: {
3102
- [appRTKQApi.reducerPath]: appRTKQApi.reducer
3331
+ [appRTKQApi.reducerPath]: appRTKQApi.reducer,
3332
+ ...additionalReducers
3103
3333
  },
3104
3334
  middleware: (getDefaultMiddleware)=>getDefaultMiddleware({
3105
3335
  serializableCheck: {
@@ -3328,8 +3558,12 @@ const groupSharedFields = (data)=>{
3328
3558
  }, {});
3329
3559
  };
3330
3560
 
3331
- const statusEndpoint = '/_status';
3332
- const processHistogramResponse = (data)=>{
3561
+ /**
3562
+ * Processes the histogram data from the given input object and returns an aggregated data object.
3563
+ *
3564
+ * @param {Record<string, unknown>} data - The input data object containing histogram information.
3565
+ * @returns {AggregationsData} An object containing the processed histogram data, structured as key-value pairs.
3566
+ */ const processHistogramResponse = (data)=>{
3333
3567
  const valueData = JSONPath({
3334
3568
  json: data,
3335
3569
  path: '$..histogram',
@@ -3349,6 +3583,42 @@ const processHistogramResponse = (data)=>{
3349
3583
  }, {});
3350
3584
  return results;
3351
3585
  };
3586
+ /**
3587
+ * Adjusts histogram data in the provided object by rounding counts below a specified minimum value.
3588
+ *
3589
+ * This function traverses the input object for histogram data and updates it such that all count values
3590
+ * falling below the defined `minValue` are set to `-1`. By default, the `minValue` is set to `100`.
3591
+ *
3592
+ * @param {Record<string, unknown>} origData - The original input data containing histogram structures to modify.
3593
+ * @param {number} [minValue=100] - The minimum value of histogram counts. Counts below this value are replaced with `-1`.
3594
+ * @returns {Record<string, unknown>} - A new object containing the modified histogram data while preserving other properties.
3595
+ */ const roundHistogramResponse = (origData, minValue = 100)=>{
3596
+ const data = {
3597
+ ...origData
3598
+ };
3599
+ const pointerData = JSONPath({
3600
+ json: data,
3601
+ path: '$..histogram',
3602
+ resultType: 'pointer'
3603
+ });
3604
+ if (pointerData.length === 0) {
3605
+ return {};
3606
+ }
3607
+ pointerData.forEach((element)=>{
3608
+ const key = element.slice(1).replace(/\//g, '.');
3609
+ const histogramData = JSONPath({
3610
+ json: data,
3611
+ path: key,
3612
+ resultType: 'value'
3613
+ });
3614
+ histogramData[0].forEach((x)=>{
3615
+ x.count = x.count < minValue ? -1 : x.count;
3616
+ });
3617
+ });
3618
+ return data;
3619
+ };
3620
+
3621
+ const statusEndpoint = '/_status';
3352
3622
  const fetchJson = async (url)=>{
3353
3623
  const res = await fetch(url, {
3354
3624
  method: 'GET',
@@ -3461,24 +3731,7 @@ const useGetStatus = ()=>{
3461
3731
  }),
3462
3732
  getAggs: builder.query({
3463
3733
  query: ({ type, fields, filters, accessibility = Accessibility.ALL })=>{
3464
- const queryStart = isFilterEmpty(filters) ? `
3465
- query getAggs {
3466
- _aggregation {
3467
- ${type} (accessibility: ${accessibility}) {` : `query getAggs ($filter: JSON) {
3468
- _aggregation {
3469
- ${type} (filter: $filter, filterSelf: false, accessibility: ${accessibility}) {`;
3470
- const query = `${queryStart}
3471
- ${fields.map((field)=>histogramQueryStrForEachField(field))}
3472
- }
3473
- }
3474
- }`;
3475
- const queryBody = {
3476
- query: query,
3477
- variables: {
3478
- filter: convertFilterSetToGqlFilter(filters)
3479
- }
3480
- };
3481
- return queryBody;
3734
+ return buildGetAggregationQuery(type, fields, filters, accessibility, false);
3482
3735
  },
3483
3736
  transformResponse: (response, _meta, args)=>{
3484
3737
  return processHistogramResponse(response?.data?._aggregation[args.type] ?? {});
@@ -3486,24 +3739,7 @@ const useGetStatus = ()=>{
3486
3739
  }),
3487
3740
  getAggsNoFilterSelf: builder.query({
3488
3741
  query: ({ type, fields, filters, accessibility = Accessibility.ALL })=>{
3489
- const queryStart = isFilterEmpty(filters) ? `
3490
- query getAggs {
3491
- _aggregation {
3492
- ${type} (accessibility: ${accessibility}) {` : `query getAggs ($filter: JSON) {
3493
- _aggregation {
3494
- ${type} (filter: $filter, filterSelf: true, accessibility: ${accessibility}) {`;
3495
- const query = `${queryStart}
3496
- ${fields.map((field)=>histogramQueryStrForEachField(field))}
3497
- }
3498
- }
3499
- }`;
3500
- const queryBody = {
3501
- query: query,
3502
- variables: {
3503
- filter: convertFilterSetToGqlFilter(filters)
3504
- }
3505
- };
3506
- return queryBody;
3742
+ return buildGetAggregationQuery(type, fields, filters, accessibility, true);
3507
3743
  },
3508
3744
  transformResponse: (response, _meta, args)=>{
3509
3745
  return processHistogramResponse(response?.data?._aggregation[args.type] ?? {});
@@ -3689,7 +3925,27 @@ const useGetIndexFields = (index)=>{
3689
3925
  const { data } = useGetFieldsForIndexQuery(index);
3690
3926
  return data ?? [];
3691
3927
  };
3692
- const { useGetRawDataAndTotalCountsQuery, useGetAccessibleDataQuery, useGetAllFieldsForTypeQuery, useGetAggsQuery, useGetAggsNoFilterSelfQuery, useLazyGetAggsQuery, useGetSubAggsQuery, useGetCountsQuery, useGetFieldCountSummaryQuery, useGetFieldsForIndexQuery, useGetSharedFieldsForIndexQuery, useGeneralGQLQuery, useLazyGeneralGQLQuery } = explorerApi;
3928
+ const buildGetAggregationQuery = (type, fields, filters, accessibility = Accessibility.ALL, filterSelf = false)=>{
3929
+ const queryStart = isFilterEmpty(filters) ? `
3930
+ query getAggs {
3931
+ _aggregation {
3932
+ ${type} (accessibility: ${accessibility}) {` : `query getAggs ($filter: JSON) {
3933
+ _aggregation {
3934
+ ${type} (filter: $filter, filterSelf: ${filterSelf ? 'true' : 'false'}, accessibility: ${accessibility}) {`;
3935
+ const query = `${queryStart}
3936
+ ${fields.map((field)=>histogramQueryStrForEachField(field))}
3937
+ }
3938
+ }
3939
+ }`;
3940
+ const queryBody = {
3941
+ query: query,
3942
+ variables: {
3943
+ filter: convertFilterSetToGqlFilter(filters)
3944
+ }
3945
+ };
3946
+ return queryBody;
3947
+ };
3948
+ const { useGetRawDataAndTotalCountsQuery, useGetAccessibleDataQuery, useGetAllFieldsForTypeQuery, useGetAggsQuery, useGetAggsNoFilterSelfQuery, useLazyGetAggsQuery, useLazyGetAggsNoFilterSelfQuery, useGetSubAggsQuery, useGetCountsQuery, useGetFieldCountSummaryQuery, useGetFieldsForIndexQuery, useGetSharedFieldsForIndexQuery, useGeneralGQLQuery, useLazyGeneralGQLQuery } = explorerApi;
3693
3949
 
3694
3950
  /**
3695
3951
  * Creates a Guppy API for fetching bulk (> 10K rows) elasticsearch data
@@ -3969,6 +4225,225 @@ const queryMultipleMDSRecords = async (guids, useAggMDS = false, signal)=>{
3969
4225
  });
3970
4226
  };
3971
4227
 
4228
+ class MissingServiceConfigurationError extends Error {
4229
+ constructor(serviceName){
4230
+ super(`Missing service configuration for ${serviceName}`);
4231
+ this.name = 'MissingServiceConfigurationError';
4232
+ }
4233
+ }
4234
+
4235
+ // Default console logger
4236
+ const defaultLogger = {
4237
+ warn: (message)=>console.warn(message),
4238
+ error: (message)=>console.error(message)
4239
+ };
4240
+
4241
+ const DefaultRemoteSupportAction = async ()=>{
4242
+ throw new Error('No remote support service registered for this service name');
4243
+ };
4244
+ class RemoteSupportServiceRegistry {
4245
+ constructor(logger = defaultLogger){
4246
+ this.services = new Map();
4247
+ this.logger = logger;
4248
+ }
4249
+ /**
4250
+ * Register a remote support service
4251
+ * @param serviceName - Unique identifier for the service
4252
+ * @param action - The action function to execute for this service
4253
+ * @throws Error if serviceName or action is invalid
4254
+ */ registerService(serviceName, action) {
4255
+ if (!serviceName?.trim()) {
4256
+ throw new Error('Service name cannot be empty or null');
4257
+ }
4258
+ if (typeof action !== 'function') {
4259
+ throw new Error('Action must be a function');
4260
+ }
4261
+ if (this.services.has(serviceName)) {
4262
+ this.logger.warn(`Service '${serviceName}' is already registered and will be overwritten.`);
4263
+ }
4264
+ this.services.set(serviceName, action);
4265
+ }
4266
+ /**
4267
+ * Get a registered service action
4268
+ * @param serviceName - The service identifier
4269
+ * @returns The registered action or default action if not found
4270
+ */ getSupportService(serviceName) {
4271
+ if (!serviceName?.trim()) {
4272
+ this.logger.error('Service name cannot be empty or null');
4273
+ return DefaultRemoteSupportAction;
4274
+ }
4275
+ const service = this.services.get(serviceName);
4276
+ if (!service) {
4277
+ this.logger.warn(`Service '${serviceName}' not registered. Using default action.`);
4278
+ throw new MissingServiceConfigurationError(serviceName);
4279
+ }
4280
+ return service;
4281
+ }
4282
+ /**
4283
+ * Check if a service is registered
4284
+ * @param serviceName - The service identifier
4285
+ * @returns true if service is registered
4286
+ */ hasService(serviceName) {
4287
+ return this.services.has(serviceName);
4288
+ }
4289
+ /**
4290
+ * Get all registered service names
4291
+ * @returns Array of registered service names
4292
+ */ getRegisteredServices() {
4293
+ return Array.from(this.services.keys());
4294
+ }
4295
+ /**
4296
+ * Unregister a service
4297
+ * @param serviceName - The service identifier
4298
+ * @returns true if service was removed, false if it wasn't registered
4299
+ */ unregisterService(serviceName) {
4300
+ return this.services.delete(serviceName);
4301
+ }
4302
+ /**
4303
+ * Clear all registered services
4304
+ */ clear() {
4305
+ this.services.clear();
4306
+ }
4307
+ /**
4308
+ * Get the number of registered services
4309
+ */ size() {
4310
+ return this.services.size;
4311
+ }
4312
+ }
4313
+ let defaultRegistryInstance = null;
4314
+ function getRemoteSupportServiceRegistry(logger) {
4315
+ if (!defaultRegistryInstance) {
4316
+ defaultRegistryInstance = new RemoteSupportServiceRegistry(logger);
4317
+ }
4318
+ return defaultRegistryInstance;
4319
+ }
4320
+
4321
+ const ZENDESK_MAX_SUBJECT_LENGTH = 255;
4322
+ const ZENDESK_DOMAIN = process.env.NEXT_PUBLIC_GEN3_ZENDESK_API || 'https://<SUBDOMAIN_NAME>.zendesk.com';
4323
+ const createZendeskTicket = async ({ subject, fullName, email, contents }, configuration)=>{
4324
+ const { zendeskSubdomainName } = configuration;
4325
+ try {
4326
+ let zendeskTicketCreationURL = `${ZENDESK_DOMAIN}/api/v2/requests`;
4327
+ if (zendeskSubdomainName) {
4328
+ zendeskTicketCreationURL = zendeskTicketCreationURL.replace('<SUBDOMAIN_NAME>', zendeskSubdomainName);
4329
+ } else {
4330
+ // This is the default Gen3 helpdesk subdomain
4331
+ zendeskTicketCreationURL = zendeskTicketCreationURL.replace('<SUBDOMAIN_NAME>', 'gen3support');
4332
+ }
4333
+ let ticketSubject = subject;
4334
+ if (subject.length > ZENDESK_MAX_SUBJECT_LENGTH) {
4335
+ ticketSubject = `${subject.substring(0, ZENDESK_MAX_SUBJECT_LENGTH - 3)}...`;
4336
+ }
4337
+ await fetch(zendeskTicketCreationURL, {
4338
+ method: 'POST',
4339
+ headers: {
4340
+ 'Content-Type': 'application/json'
4341
+ },
4342
+ body: JSON.stringify({
4343
+ request: {
4344
+ subject: ticketSubject,
4345
+ comment: {
4346
+ body: contents
4347
+ },
4348
+ requester: {
4349
+ name: fullName,
4350
+ email
4351
+ }
4352
+ }
4353
+ })
4354
+ }).then((response)=>{
4355
+ if (response.status !== 201) {
4356
+ throw new Error(`Request for create Zendesk ticket failed with status ${response.status}`);
4357
+ }
4358
+ return response;
4359
+ });
4360
+ } catch (err) {
4361
+ throw new Error(`Request for create Zendesk ticket failed: ${err}`);
4362
+ }
4363
+ };
4364
+
4365
+ const registerDefaultRemoteSupport = ()=>{
4366
+ const registry = getRemoteSupportServiceRegistry();
4367
+ registry.registerService('zenDesk', createZendeskTicket);
4368
+ };
4369
+
4370
+ /**
4371
+ * Converts a Partial<RequestListQuery> object to a URL query string
4372
+ * @param params - The parameters to convert
4373
+ * @returns A formatted query string (including the leading '?')
4374
+ */ const convertToQueryString = (params)=>{
4375
+ if (!params || Object.keys(params).length === 0) {
4376
+ return '';
4377
+ }
4378
+ const queryParts = [];
4379
+ // Handle policy_ids array
4380
+ if (params.policy_ids && params.policy_ids.length > 0) {
4381
+ params.policy_ids.forEach((id)=>{
4382
+ queryParts.push(`policy_id=${encodeURIComponent(id)}`);
4383
+ });
4384
+ }
4385
+ if (params.resource_ids && params.resource_ids.length > 0) {
4386
+ params.resource_ids.forEach((id)=>{
4387
+ queryParts.push(`resource_id=${encodeURIComponent(id)}`);
4388
+ });
4389
+ }
4390
+ // Handle status
4391
+ if (params.status !== undefined) {
4392
+ queryParts.push(`status=${encodeURIComponent(params.status)}`);
4393
+ }
4394
+ // Handle revoke
4395
+ if (params.revoke !== undefined) {
4396
+ queryParts.push(`revoke=${params.revoke}`);
4397
+ }
4398
+ return queryParts.length > 0 ? `?${queryParts.join('&')}` : undefined;
4399
+ };
4400
+ /**
4401
+ * Defines requester service using a base URL and expected endpoints. Derived from gen3Api core API.
4402
+ *
4403
+ * @param endpoints - Defines endpoints used in discovery page
4404
+ * @param request - Queries Requestor service
4405
+ * @see https://github.com/uc-cdis/requestor?tab=readme-ov-file#requestor
4406
+ * @see https://petstore.swagger.io/?url=https://raw.githubusercontent.com/uc-cdis/requestor/master/docs/openapi.yaml#/Query/list_requests_request_get
4407
+ * @returns: Object of request made
4408
+ */ //TODO convert snakeCase yTpes o camelCase by adding transform respomse
4409
+ const requestorApi = gen3Api.injectEndpoints({
4410
+ endpoints: (builder)=>({
4411
+ status: builder.query({
4412
+ // get status of requestor service
4413
+ query: ()=>`${GEN3_REQUESTOR_API}/_status`
4414
+ }),
4415
+ request: builder.query({
4416
+ query: (params)=>{
4417
+ const strParams = params ? convertToQueryString(params) : undefined;
4418
+ return `${GEN3_REQUESTOR_API}/request${strParams ?? ''}`;
4419
+ }
4420
+ }),
4421
+ userRequest: builder.query({
4422
+ // get a list of requests
4423
+ query: (params)=>{
4424
+ const strParams = params ? convertToQueryString(params) : undefined;
4425
+ return `${GEN3_REQUESTOR_API}/request/user${strParams ?? ''}`;
4426
+ }
4427
+ }),
4428
+ requestById: builder.query({
4429
+ query: (requestId)=>`${GEN3_REQUESTOR_API}/request/${requestId}`
4430
+ }),
4431
+ createRequest: builder.mutation({
4432
+ query: (queryBody)=>({
4433
+ url: `${GEN3_REQUESTOR_API}/request`,
4434
+ method: 'POST',
4435
+ credentials: 'include',
4436
+ headers: {
4437
+ Accept: 'application/json',
4438
+ 'Content-Type': 'application/json'
4439
+ },
4440
+ body: JSON.stringify(queryBody)
4441
+ })
4442
+ })
4443
+ })
4444
+ });
4445
+ const { useCreateRequestMutation, useRequestQuery, useLazyRequestQuery, useStatusQuery: useRequestorStatusQuery, useRequestByIdQuery, useUserRequestQuery } = requestorApi;
4446
+
3972
4447
  /**
3973
4448
  * Creates a loadingStatusApi for checking the status of a sower data download job
3974
4449
  * @param getJobList Shows the list of jobs currently running
@@ -4058,7 +4533,7 @@ const extractValuesFromObject = (jsonPathMappings, obj)=>{
4058
4533
  };
4059
4534
  for(const key in jsonPathMappings){
4060
4535
  if (key in Object.keys(jsonPathMappings)) {
4061
- // Extract value from object and store it in the result.
4536
+ // Extract value from an object and store it in the result.
4062
4537
  result[key] = extractObjectValue(jsonPathMappings[key], obj);
4063
4538
  }
4064
4539
  }
@@ -4347,5 +4822,5 @@ const selectPaymodelStatus = createSelector(paymodelStatusSelector, (status)=>st
4347
4822
  const isWorkspaceActive = (status)=>status === WorkspaceStatus.Running || status === WorkspaceStatus.Launching || status === WorkspaceStatus.Terminating;
4348
4823
  const isWorkspaceRunningOrStopping = (status)=>status === WorkspaceStatus.Running || status === WorkspaceStatus.Terminating;
4349
4824
 
4350
- export { Accessibility, CoreProvider, DataLibraryStoreMode, EmptyWorkspaceStatusResponse, GEN3_API, GEN3_AUTHZ_API, GEN3_COMMONS_NAME, GEN3_CROSSWALK_API, GEN3_DOMAIN, GEN3_DOWNLOADS_ENDPOINT, GEN3_FENCE_API, GEN3_GUPPY_API, GEN3_MANIFEST_API, GEN3_MDS_API, GEN3_REDIRECT_URL, GEN3_SOWER_API, GEN3_SUBMISSION_API, GEN3_WORKSPACE_API, HTTPError, HTTPErrorMessages, HttpMethod, Modals, PodConditionType, PodStatus, RequestedWorkspaceStatus, WorkspaceStatus, buildListItemsGroupedByDataset, clearActiveWorkspaceId, clearCohortFilters, convertFilterSetToGqlFilter, coreStore, createAppApiForRTKQ, createAppStore, createGen3App, createGen3AppWithOwnStore, createUseCoreDataHook, downloadFromGuppyToBlob, downloadJSONDataFromGuppy, drsHostnamesReducer, extractEnumFilterValue, extractFieldNameFromFullFieldName, extractFileDatasetsInRecords, extractFilterValue, extractIndexAndFieldNameFromFullFieldName, extractIndexFromDataLibraryCohort, extractIndexFromFullFieldName, fetchFence, fetchFencePresignedURL, fetchJSONDataFromURL, fetchJson, fetchUserState, fieldNameToTitle, gen3Api, getCurrentTimestamp, getFederatedLoginStatus, getGen3AppId, getNumberOfItemsInDatalist, getTimestamp, graphQLAPI, graphQLWithTags, groupSharedFields, guppyAPISliceMiddleware, guppyApi, guppyApiReducer, guppyApiSliceReducerPath, handleOperation, hideModal, isAdditionalDataItem, isArray, isAuthenticated, isCohortItem, isDataLibraryAPIResponse, isDatalistAPI, isErrorWithMessage, isFetchBaseQueryError, isFetchError, isFetchParseError, isFileItem, isFilterEmpty, isFilterSet, isGuppyAggregationData, isHistogramData, isHistogramDataAArray, isHistogramDataAnEnum, isHistogramDataArray, isHistogramDataArrayARange, isHistogramDataArrayAnEnum, isHistogramDataCollection, isHistogramRangeData, isHttpStatusError, isIntersection, isJSONObject, isJSONValue, isJSONValueArray, isNotDefined, isObject, isOperationWithField, isOperatorWithFieldAndArrayOfOperands, isPending, isProgramUrl, isRootUrl, isString, isTimeGreaterThan, isUnion, isWorkspaceActive, isWorkspaceRunningOrStopping, listifyMethodsFromMapping, logoutFence, manifestApi, manifestTags, prepareUrl$1 as prepareUrl, prependIndexToFieldName, processHistogramResponse, projectCodeFromResourcePath, queryMultipleMDSRecords, rawDataQueryStrForEachField, removeCohortFilter, resetUserState, resourcePathFromProjectID, selectActiveWorkspaceId, selectActiveWorkspaceStatus, selectAllCohortFiltersCollapsed, selectAuthzMappingData, selectCSRFToken, selectCSRFTokenData, selectCohortFilterCombineMode, selectCohortFilterExpanded, selectCohortFilters, selectCurrentCohort, selectCurrentCohortId, selectCurrentCohortName, selectCurrentMessage, selectCurrentModal, selectGen3AppByName, selectGen3AppMetadataByName, selectHeadersWithCSRFToken, selectIndexFilters, selectIndexedFilterByName, selectPaymodelStatus, selectRequestedWorkspaceStatus, selectRequestedWorkspaceStatusTimestamp, selectSharedFilters, selectSharedFiltersForFields, selectShouldShareFilters, selectUser, selectUserAuthStatus, selectUserData, selectUserDetails, selectUserLoginStatus, selectWorkspaceStatus, selectWorkspaceStatusFromService, setActiveWorkspace, setActiveWorkspaceId, setActiveWorkspaceStatus, setCohortFilter, setCohortFilterCombineMode, setCohortIndexFilters, setDRSHostnames, setRequestedWorkspaceStatus, setSharedFilters, setShouldShareFilters, setupCoreStore, showModal, submissionApi, toggleCohortBuilderAllFilters, toggleCohortBuilderCategoryFilter, trimFirstFieldNameToTitle, updateCohortFilter, useAddCohortManifestMutation, useAddFileManifestMutation, useAddMetadataManifestMutation, useAddNewCredentialMutation, useAskQuestionMutation, useAuthorizeFromCredentialsMutation, useCoreDispatch, useCoreSelector, useDataLibrary, useDownloadFromGuppyMutation, useFetchUserDetailsQuery, useGeneralGQLQuery, useGetAISearchStatusQuery, useGetAISearchVersionQuery, useGetAccessibleDataQuery, useGetActivePayModelQuery, useGetAggMDSQuery, useGetAggsNoFilterSelfQuery, useGetAggsQuery, useGetAllFieldsForTypeQuery, useGetArrayTypes, useGetAuthzMappingsQuery, useGetCSRFQuery, useGetCohortManifestQuery, useGetCountsQuery, useGetCredentialsQuery, useGetCrosswalkDataQuery, useGetDataQuery, useGetDictionaryQuery, useGetDownloadQuery, useGetExternalLoginsQuery, useGetFederatedLoginStatus, useGetFieldCountSummaryQuery, useGetFieldsForIndexQuery, useGetFileFromManifestQuery, useGetFileManifestQuery, useGetIndexAggMDSQuery, useGetIndexFields, useGetJWKKeysQuery, useGetLoginProvidersQuery, useGetMDSQuery, useGetManifestServiceStatusQuery, useGetMetadataByIdQuery, useGetMetadataFromManifestQuery, useGetMetadataManifestQuery, useGetProjectsDetailsQuery, useGetProjectsQuery, useGetRawDataAndTotalCountsQuery, useGetSharedFieldsForIndexQuery, useGetSowerJobListQuery, useGetSowerJobStatusQuery, useGetSowerOutputQuery, useGetSowerServiceStatusQuery, useGetStatus, useGetSubAggsQuery, useGetSubmissionGraphQLQuery, useGetSubmissionsQuery, useGetTagsQuery, useGetWorkspaceOptionsQuery, useGetWorkspacePayModelsQuery, useGetWorkspaceStatusQuery, useGraphQLQuery, useIsExternalConnectedQuery, useIsUserLoggedIn, useLaunchWorkspaceMutation, useLazyFetchUserDetailsQuery, useLazyGeneralGQLQuery, useLazyGetAggsQuery, useLazyGetAuthzMappingsQuery, useLazyGetCrosswalkDataQuery, useLazyGetDownloadQuery, useLazyGetExternalLoginsQuery, useLazyGetManifestServiceStatusQuery, useLazyGetProjectsQuery, useLazyGetSowerJobListQuery, useLazyGetSubmissionGraphQLQuery, useLazyIsExternalConnectedQuery, usePrevious, useRemoveCredentialMutation, useSetCurrentPayModelMutation, useSubmitSowerJobMutation, useTerminateWorkspaceMutation, useUserAuth, userHasCreateOrUpdateOnAnyProject, userHasDataUpload, userHasMethodForServiceOnProject, userHasMethodForServiceOnResource, userHasMethodOnAnyProject, userHasSheepdogProgramAdmin, userHasSheepdogProjectAdmin };
4825
+ export { Accessibility, CoreProvider, DataLibraryStoreMode, EmptyWorkspaceStatusResponse, GEN3_API, GEN3_AUTHZ_API, GEN3_COMMONS_NAME, GEN3_CROSSWALK_API, GEN3_DOMAIN, GEN3_DOWNLOADS_ENDPOINT, GEN3_FENCE_API, GEN3_GUPPY_API, GEN3_MANIFEST_API, GEN3_MDS_API, GEN3_REDIRECT_URL, GEN3_SOWER_API, GEN3_SUBMISSION_API, GEN3_WORKSPACE_API, HTTPError, HTTPErrorMessages, HttpMethod, MissingServiceConfigurationError, Modals, PodConditionType, PodStatus, RequestedWorkspaceStatus, WorkspaceStatus, addNewDefaultUnsavedCohort, buildGetAggregationQuery, buildListItemsGroupedByDataset, clearActiveWorkspaceId, clearCohortFilters, cohortReducer, convertFilterSetToGqlFilter, convertFilterToGqlFilter, convertToQueryString, coreStore, createAppApiForRTKQ, createAppStore, createGen3App, createGen3AppWithOwnStore, createUseCoreDataHook, downloadFromGuppyToBlob, downloadJSONDataFromGuppy, drsHostnamesReducer, extractEnumFilterValue, extractFieldNameFromFullFieldName, extractFileDatasetsInRecords, extractFilterValue, extractIndexAndFieldNameFromFullFieldName, extractIndexFromDataLibraryCohort, extractIndexFromFullFieldName, fetchFence, fetchFencePresignedURL, fetchJSONDataFromURL, fetchJson, fetchUserState, fieldNameToTitle, gen3Api, getCurrentTimestamp, getFederatedLoginStatus, getGen3AppId, getNumberOfItemsInDatalist, getRemoteSupportServiceRegistry, getTimestamp, graphQLAPI, graphQLWithTags, groupSharedFields, guppyAPISliceMiddleware, guppyApi, guppyApiReducer, guppyApiSliceReducerPath, handleOperation, hideModal, histogramQueryStrForEachField, isAdditionalDataItem, isArray, isAuthenticated, isCohortItem, isDataLibraryAPIResponse, isDatalistAPI, isErrorWithMessage, isFetchBaseQueryError, isFetchError, isFetchParseError, isFileItem, isFilterEmpty, isFilterSet, isGuppyAggregationData, isHistogramData, isHistogramDataAArray, isHistogramDataAnEnum, isHistogramDataArray, isHistogramDataArrayARange, isHistogramDataArrayAnEnum, isHistogramDataCollection, isHistogramRangeData, isHttpStatusError, isIntersection, isJSONObject, isJSONValue, isJSONValueArray, isNotDefined, isObject, isOperandsType, isOperationWithField, isOperatorWithFieldAndArrayOfOperands, isPending, isProgramUrl, isRootUrl, isString, isTimeGreaterThan, isUnion, isWorkspaceActive, isWorkspaceRunningOrStopping, listifyMethodsFromMapping, logoutFence, manifestApi, manifestTags, nestedHistogramQueryStrForEachField, prepareUrl$1 as prepareUrl, prependIndexToFieldName, processHistogramResponse, projectCodeFromResourcePath, queryMultipleMDSRecords, rawDataQueryStrForEachField, registerDefaultRemoteSupport, removeCohort, removeCohortFilter, requestorApi, resetUserState, resourcePathFromProjectID, roundHistogramResponse, selectActiveWorkspaceId, selectActiveWorkspaceStatus, selectAllCohortFiltersCollapsed, selectAuthzMappingData, selectAvailableCohorts, selectCSRFToken, selectCSRFTokenData, selectCohortFilterCombineMode, selectCohortFilterExpanded, selectCohortFilters, selectCurrentCohort, selectCurrentCohortId, selectCurrentCohortModified, selectCurrentCohortName, selectCurrentCohortSaved, selectCurrentMessage, selectCurrentModal, selectGen3AppByName, selectGen3AppMetadataByName, selectHeadersWithCSRFToken, selectIndexFilters, selectIndexedFilterByName, selectPaymodelStatus, selectRequestedWorkspaceStatus, selectRequestedWorkspaceStatusTimestamp, selectSharedFilters, selectSharedFiltersForFields, selectShouldShareFilters, selectUser, selectUserAuthStatus, selectUserData, selectUserDetails, selectUserLoginStatus, selectWorkspaceStatus, selectWorkspaceStatusFromService, setActiveCohort, setActiveCohortList, setActiveWorkspace, setActiveWorkspaceId, setActiveWorkspaceStatus, setCohortFilter, setCohortFilterCombineMode, setCohortIndexFilters, setDRSHostnames, setRequestedWorkspaceStatus, setSharedFilters, setShouldShareFilters, setupCoreStore, showModal, submissionApi, toggleCohortBuilderAllFilters, toggleCohortBuilderCategoryFilter, trimFirstFieldNameToTitle, updateCohortFilter, useAddCohortManifestMutation, useAddFileManifestMutation, useAddMetadataManifestMutation, useAddNewCredentialMutation, useAskQuestionMutation, useAuthorizeFromCredentialsMutation, useCoreDispatch, useCoreSelector, useCreateAuthzResourceMutation, useCreateRequestMutation, useDataLibrary, useDownloadFromGuppyMutation, useFetchUserDetailsQuery, useGeneralGQLQuery, useGetAISearchStatusQuery, useGetAISearchVersionQuery, useGetAccessibleDataQuery, useGetActivePayModelQuery, useGetAggMDSQuery, useGetAggsNoFilterSelfQuery, useGetAggsQuery, useGetAllFieldsForTypeQuery, useGetArrayTypes, useGetAuthzMappingsQuery, useGetAuthzResourcesQuery, useGetCSRFQuery, useGetCohortManifestQuery, useGetCountsQuery, useGetCredentialsQuery, useGetCrosswalkDataQuery, useGetDataQuery, useGetDictionaryQuery, useGetDownloadQuery, useGetExternalLoginsQuery, useGetFederatedLoginStatus, useGetFieldCountSummaryQuery, useGetFieldsForIndexQuery, useGetFileFromManifestQuery, useGetFileManifestQuery, useGetIndexAggMDSQuery, useGetIndexFields, useGetJWKKeysQuery, useGetLoginProvidersQuery, useGetMDSQuery, useGetManifestServiceStatusQuery, useGetMetadataByIdQuery, useGetMetadataFromManifestQuery, useGetMetadataManifestQuery, useGetProjectsDetailsQuery, useGetProjectsQuery, useGetRawDataAndTotalCountsQuery, useGetSharedFieldsForIndexQuery, useGetSowerJobListQuery, useGetSowerJobStatusQuery, useGetSowerOutputQuery, useGetSowerServiceStatusQuery, useGetStatus, useGetSubAggsQuery, useGetSubmissionGraphQLQuery, useGetSubmissionsQuery, useGetTagsQuery, useGetWorkspaceOptionsQuery, useGetWorkspacePayModelsQuery, useGetWorkspaceStatusQuery, useGraphQLQuery, useIsExternalConnectedQuery, useIsUserLoggedIn, useLaunchWorkspaceMutation, useLazyFetchUserDetailsQuery, useLazyGeneralGQLQuery, useLazyGetAggsNoFilterSelfQuery, useLazyGetAggsQuery, useLazyGetAuthzMappingsQuery, useLazyGetAuthzResourcesQuery, useLazyGetCSRFQuery, useLazyGetCrosswalkDataQuery, useLazyGetDownloadQuery, useLazyGetExternalLoginsQuery, useLazyGetManifestServiceStatusQuery, useLazyGetProjectsQuery, useLazyGetSowerJobListQuery, useLazyGetSubmissionGraphQLQuery, useLazyIsExternalConnectedQuery, useLazyRequestQuery, usePrevious, useRemoveCredentialMutation, useRequestByIdQuery, useRequestQuery, useRequestorStatusQuery, useSetCurrentPayModelMutation, useSubmitSowerJobMutation, useTerminateWorkspaceMutation, useUserAuth, useUserRequestQuery, userHasCreateOrUpdateOnAnyProject, userHasDataUpload, userHasMethodForServiceOnProject, userHasMethodForServiceOnResource, userHasMethodOnAnyProject, userHasSheepdogProgramAdmin, userHasSheepdogProjectAdmin };
4351
4826
  //# sourceMappingURL=index.js.map