@gen3/core 0.12.22 → 0.12.24

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 (39) hide show
  1. package/dist/cjs/constants.js +1 -0
  2. package/dist/cjs/constants.js.map +1 -1
  3. package/dist/cjs/index.js +1117 -891
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/cjs/server.js +1 -0
  6. package/dist/cjs/server.js.map +1 -1
  7. package/dist/constants.d.ts +2 -1
  8. package/dist/dts/constants.d.ts +1 -0
  9. package/dist/dts/constants.d.ts.map +1 -1
  10. package/dist/dts/features/cohortComparison/cohortFacetSlice.d.ts +201 -0
  11. package/dist/dts/features/cohortComparison/cohortFacetSlice.d.ts.map +1 -0
  12. package/dist/dts/features/cohortComparison/index.d.ts +7 -0
  13. package/dist/dts/features/cohortComparison/index.d.ts.map +1 -0
  14. package/dist/dts/features/cohortComparison/pValueApi.d.ts +186 -0
  15. package/dist/dts/features/cohortComparison/pValueApi.d.ts.map +1 -0
  16. package/dist/dts/features/cohortComparison/types.d.ts +74 -0
  17. package/dist/dts/features/cohortComparison/types.d.ts.map +1 -0
  18. package/dist/dts/features/cohortComparison/vennDiagramSlice.d.ts +198 -0
  19. package/dist/dts/features/cohortComparison/vennDiagramSlice.d.ts.map +1 -0
  20. package/dist/dts/features/filters/index.d.ts +1 -0
  21. package/dist/dts/features/filters/index.d.ts.map +1 -1
  22. package/dist/dts/features/filters/nestedFilters.d.ts +0 -2
  23. package/dist/dts/features/filters/nestedFilters.d.ts.map +1 -1
  24. package/dist/dts/features/filters/utils.d.ts +2 -2
  25. package/dist/dts/features/guppy/guppySlice.d.ts +566 -0
  26. package/dist/dts/features/guppy/guppySlice.d.ts.map +1 -1
  27. package/dist/dts/index.d.ts +1 -0
  28. package/dist/dts/index.d.ts.map +1 -1
  29. package/dist/dts/types/types.d.ts +15 -13
  30. package/dist/dts/types/types.d.ts.map +1 -1
  31. package/dist/esm/constants.js +1 -0
  32. package/dist/esm/constants.js.map +1 -1
  33. package/dist/esm/index.js +1103 -890
  34. package/dist/esm/index.js.map +1 -1
  35. package/dist/esm/server.js +1 -0
  36. package/dist/esm/server.js.map +1 -1
  37. package/dist/index.d.ts +7633 -6431
  38. package/package.json +2 -2
  39. package/LICENSE +0 -201
package/dist/cjs/index.js CHANGED
@@ -64,6 +64,7 @@ const GEN3_CROSSWALK_API = process.env.NEXT_PUBLIC_GEN3_CROSSWALK_API || `${GEN3
64
64
  const GEN3_SOWER_API = process.env.NEXT_PUBLIC_GEN3_SOWER_API || `${GEN3_API}/jobs`;
65
65
  const GEN3_MANIFEST_API = process.env.NEXT_PUBLIC_GEN3_MANIFEST_API || `${GEN3_API}/manifests`;
66
66
  const GEN3_REQUESTOR_API = process.env.NEXT_PUBLIC_GEN3_REQUESTOR_API || `${GEN3_API}/requestor`;
67
+ const GEN3_ANALYSIS_API = process.env.NEXT_PUBLIC_GEN3_ANALYSIS_API || `${GEN3_API}/analysis/v0`;
67
68
  var Accessibility = /*#__PURE__*/ function(Accessibility) {
68
69
  Accessibility["ACCESSIBLE"] = "accessible";
69
70
  Accessibility["UNACCESSIBLE"] = "unaccessible";
@@ -1780,12 +1781,12 @@ const COMMON_PREPOSITIONS = [
1780
1781
  'yet'
1781
1782
  ];
1782
1783
  const capitalize = (s)=>s.length > 0 ? s[0].toUpperCase() + s.slice(1) : '';
1783
- const trimFirstFieldNameToTitle = (fieldName, trim = false)=>{
1784
+ const trimFirstfieldNameToLabel = (fieldName, trim = false)=>{
1784
1785
  if (trim) {
1785
1786
  const source = fieldName.slice(fieldName.indexOf('.') + 1);
1786
- return fieldNameToTitle(source ? source : fieldName, 0);
1787
+ return fieldNameToLabel(source ? source : fieldName, 0);
1787
1788
  }
1788
- return fieldNameToTitle(fieldName);
1789
+ return fieldNameToLabel(fieldName);
1789
1790
  };
1790
1791
  /**
1791
1792
  * Converts a filter name to a title,
@@ -1793,7 +1794,7 @@ const trimFirstFieldNameToTitle = (fieldName, trim = false)=>{
1793
1794
  * if sections == 2 then the output would be Input Experimental Strategy
1794
1795
  * @param fieldName input filter expected to be: string.firstpart_secondpart
1795
1796
  * @param sections number of "sections" string.string.string to got back from the end of the field
1796
- */ const fieldNameToTitle = (fieldName, sections = 1)=>{
1797
+ */ const fieldNameToLabel = (fieldName, sections = 1)=>{
1797
1798
  if (fieldName === undefined) return 'No Title';
1798
1799
  return fieldName.split('.').slice(-sections).map((s)=>s.split('_')).flat().map((word)=>COMMON_PREPOSITIONS.includes(word) ? word : capitalize(word)).map((word)=>word in FieldNameOverrides ? FieldNameOverrides[word] : word).join(' ');
1799
1800
  };
@@ -1817,492 +1818,808 @@ const trimFirstFieldNameToTitle = (fieldName, trim = false)=>{
1817
1818
  ];
1818
1819
  };
1819
1820
 
1820
- const defaultCohortNameGenerator = ()=>`Custom cohort ${new Date().toLocaleString('en-CA', {
1821
- timeZone: 'America/Chicago',
1822
- hour12: false
1823
- }).replace(',', '')}`;
1824
- const isNameUnique = (entities, name, excludeId)=>{
1825
- const trimmedName = name.trim();
1826
- if (!trimmedName) return false;
1827
- return !entities.some((cohort)=>cohort && cohort.id !== excludeId && cohort.name.trim().toLowerCase() === trimmedName.toLowerCase());
1828
- };
1829
- const generateUniqueName = (entities, baseName)=>{
1830
- const trimmedBaseName = baseName.trim();
1831
- // If base name is unique, use it
1832
- if (isNameUnique(entities, trimmedBaseName)) {
1833
- return trimmedBaseName;
1834
- }
1835
- // Find a unique name by appending numbers
1836
- let counter = 1;
1837
- let uniqueName;
1838
- do {
1839
- uniqueName = `${trimmedBaseName} (${counter})`;
1840
- counter++;
1841
- }while (!isNameUnique(entities, uniqueName))
1842
- return uniqueName;
1843
- };
1844
1821
  /**
1845
- * This function takes a FilterSet object and a prefix string as input.
1846
- * It filters the root property of the FilterSet object and returns a
1847
- * new FilterSet object that only contains filters with field names
1848
- * that start with the specified prefix.
1822
+ * Constructs a nested operation object based on the provided field and leaf operand.
1823
+ * If the field does not contain a dot '.', it either assigns the field to the leaf operand (if applicable)
1824
+ * or returns the leaf operand as is. When the field contains dots, it splits the field into parts,
1825
+ * creates a "nested" operation for the root field, and recursively constructs the nested structure
1826
+ * for the remaining portion of the field.
1849
1827
  *
1850
- * @param fs - The FilterSet object to filter
1851
- * @param prefix - The prefix to filter by
1852
- * @returns - A new FilterSet object that only contains filters with field names that start with the specified prefix
1853
- * @category Filters
1854
- */ const extractFiltersWithPrefixFromFilterSet = (fs, prefix)=>{
1855
- if (fs === undefined || fs.root === undefined) {
1856
- return {
1857
- mode: 'and',
1858
- root: {}
1859
- };
1828
+ * @param {string} field - The hierarchical field path, with segments separated by dots (e.g., "root.child").
1829
+ * @param {Operation} leafOperand - The operation to be nested within the specified path.
1830
+ * @param parentPath - The parent path of the current field. Guppy nested filters require a parent path.
1831
+ * @param depth
1832
+ * @returns {Operation} A nested operation object that represents the structured path and operand.
1833
+ */ const buildNestedWithParentPathGQLFilter = (field, leafOperand, parentPath = undefined)=>{
1834
+ if (!field.includes('.')) {
1835
+ return leafOperand;
1860
1836
  }
1861
- return Object.values(fs.root).reduce((acc, filter)=>{
1862
- if (isIntersectionOrUnion(filter) || isNestedFilter(filter)) return acc;
1863
- if (filter.field.startsWith(prefix)) {
1864
- acc.root[filter.field] = filter;
1837
+ const splitFieldArray = field.split('.');
1838
+ const nextField = splitFieldArray.shift();
1839
+ if (!nextField) {
1840
+ console.warn('Invalid field path:', field);
1841
+ return leafOperand;
1842
+ }
1843
+ const currentPath = parentPath ? `${parentPath}.${nextField}` : nextField;
1844
+ return {
1845
+ nested: {
1846
+ path: currentPath,
1847
+ ...buildNestedGQLFilter(splitFieldArray.join('.'), leafOperand, currentPath)
1865
1848
  }
1866
- return acc;
1867
- }, {
1868
- mode: 'and',
1869
- root: {}
1870
- });
1849
+ };
1850
+ };
1851
+ const buildCohortGqlOperator = (fs)=>{
1852
+ if (!fs || !fs.root) return undefined;
1853
+ const fsKeys = Object.keys(fs.root);
1854
+ // if no keys return undefined
1855
+ if (fsKeys.length === 0) return undefined;
1856
+ // TODO consider changing FilterSet: mode to support joinOrToAll as FilterSet mode
1857
+ // find key using keyword "joinOrToAll"
1858
+ const joinOrToAllKey = fsKeys.filter((x)=>x.includes('joinOrToAll'));
1859
+ switch(fs.mode){
1860
+ case 'and':
1861
+ if (joinOrToAllKey.length === 1) {
1862
+ const firstJoinOrToAllKey = joinOrToAllKey[0];
1863
+ // Remove firstJoinOrToAllKey from Array
1864
+ fsKeys.splice(fsKeys.indexOf(firstJoinOrToAllKey), 1);
1865
+ const firstJoinOrToAllObj = fs.root[firstJoinOrToAllKey];
1866
+ // make sure type is or/ Union
1867
+ if (firstJoinOrToAllObj.operator === 'or') {
1868
+ return {
1869
+ or: firstJoinOrToAllObj?.operands.map((orObj)=>{
1870
+ // go through each or statement and add all other filters to it
1871
+ return {
1872
+ and: [
1873
+ convertFilterToNestedGqlFilter(orObj),
1874
+ ...fsKeys.map((k)=>{
1875
+ return convertFilterToNestedGqlFilter(fs.root[k]);
1876
+ })
1877
+ ]
1878
+ };
1879
+ })
1880
+ };
1881
+ } else {
1882
+ console.error(`function buildCohortGqlOperator expecting "or" received "${firstJoinOrToAllObj.operator}" on key "${firstJoinOrToAllKey}"`);
1883
+ }
1884
+ } else if (joinOrToAllKey.length > 1) {
1885
+ console.error(`function buildCohortGqlOperator expecting only one joinOrToAll received: ${joinOrToAllKey.length}`, fsKeys);
1886
+ }
1887
+ return {
1888
+ // TODO: Replace fixed AND with cohort top level operation like Union or Intersection
1889
+ [fs.mode]: fsKeys.map((k)=>{
1890
+ return convertFilterToGqlFilter(fs.root[k]);
1891
+ })
1892
+ };
1893
+ case 'or':
1894
+ return {
1895
+ [fs.mode]: fsKeys.map((k)=>{
1896
+ return convertFilterToGqlFilter(fs.root[k]);
1897
+ })
1898
+ };
1899
+ }
1871
1900
  };
1872
-
1873
1901
  /**
1874
- * Cohorts in Gen3 are defined as a set of filters for each index in the data.
1875
- * This means one cohort id defined for all "tabs" in CohortBuilder (explorer)
1876
- * Switching a cohort id means all the cohorts for the index are changed.
1877
- */ const DEFAULT_COHORT_NAME = 'Cohort';
1878
- const newCohort = ({ filters = {}, customName })=>{
1879
- const ts = new Date().toISOString();
1880
- const newName = customName ?? defaultCohortNameGenerator();
1881
- const newId = createCohortId();
1902
+ * Merged two FilterSets returning the merged pair.
1903
+ * @param a - first FilterSet
1904
+ * @param b - other FilterSet
1905
+ */ const joinFilters = (a, b)=>{
1882
1906
  return {
1883
- name: newName,
1884
- id: newId,
1885
- filters: filters ?? {},
1886
- modified: false,
1887
- saved: false,
1888
- createdDatetime: ts,
1889
- modifiedDatetime: ts,
1890
- counts: {}
1907
+ mode: a.mode,
1908
+ root: {
1909
+ ...a.root,
1910
+ ...b.root
1911
+ }
1891
1912
  };
1892
1913
  };
1893
- const nanoid = nanoid$1.customAlphabet('1234567890abcdef', 16);
1894
- const createCohortId = ()=>nanoid();
1895
- const cohortsAdapter = toolkit.createEntityAdapter({
1896
- sortComparer: (a, b)=>{
1897
- if (a.modifiedDatetime <= b.modifiedDatetime) return 1;
1898
- else return -1;
1899
- },
1900
- selectId: (cohort)=>cohort.id
1901
- });
1902
- // Create an initial unsaved cohort
1903
- const initialCohort = newCohort({
1904
- customName: DEFAULT_COHORT_NAME
1905
- });
1906
- const emptyInitialState = cohortsAdapter.getInitialState({
1907
- currentCohortId: initialCohort.id,
1908
- message: undefined
1909
- });
1910
- // Set the initial cohort in the adapter state
1911
- const initialState$3 = cohortsAdapter.setOne(emptyInitialState, initialCohort);
1912
- const getCurrentCohortId = (state)=>state.currentCohortId;
1913
- /**
1914
- * Redux slice for cohort filters
1915
- */ const cohortManagerSlice = toolkit.createSlice({
1916
- name: 'cohort',
1917
- initialState: initialState$3,
1918
- reducers: {
1919
- createNewCohort: (state, action)=>{
1920
- const baseName = action.payload.name || `Cohort`;
1921
- const uniqueName = generateUniqueName(Object.values(state.entities), baseName);
1922
- const cohort = newCohort({
1923
- filters: action.payload.filters,
1924
- customName: uniqueName
1925
- });
1926
- cohortsAdapter.addOne(state, cohort);
1927
- if (action.payload?.setAsCurrent) {
1928
- state.currentCohortId = cohort.id;
1914
+ const convertFilterSetToOperation = (fs)=>{
1915
+ if (!fs) return undefined;
1916
+ switch(fs.mode){
1917
+ case 'and':
1918
+ return Object.keys(fs.root).length == 0 ? undefined : {
1919
+ operator: fs.mode,
1920
+ operands: Object.keys(fs.root).map((k)=>{
1921
+ return fs.root[k];
1922
+ })
1923
+ };
1924
+ }
1925
+ return undefined;
1926
+ };
1927
+ const extractContents = (filter)=>{
1928
+ if (isGQLUnion(filter)) {
1929
+ return filter.or;
1930
+ }
1931
+ if (isGQLIntersection(filter)) {
1932
+ return filter.and;
1933
+ }
1934
+ return undefined;
1935
+ };
1936
+ class ToGqlAllNested {
1937
+ constructor(){
1938
+ this.handleEquals = (op)=>{
1939
+ if (op.field.includes('.')) {
1940
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
1941
+ return buildNestedGQLFilter(op.field, {
1942
+ '=': {
1943
+ [leafField]: op.operand
1944
+ }
1945
+ });
1929
1946
  }
1930
- },
1931
- updateCohortName: (state, action)=>{
1932
- const { id, name } = action.payload;
1933
- cohortsAdapter.updateOne(state, {
1934
- id: id,
1935
- changes: {
1936
- name: name,
1937
- modified: true,
1938
- modifiedDatetime: new Date().toISOString()
1947
+ return {
1948
+ '=': {
1949
+ [op.field]: op.operand
1939
1950
  }
1940
- });
1941
- },
1942
- removeCohort: (state, action)=>{
1943
- const { id: cohortId } = action.payload;
1944
- const removedCohortName = state.entities[cohortId].name;
1945
- const totalCohorts = Object.keys(state.entities).length;
1946
- if (totalCohorts <= 1) {
1947
- cohortsAdapter.removeAll(state);
1948
- const defaultCohort = newCohort({
1949
- filters: {},
1950
- customName: DEFAULT_COHORT_NAME
1951
+ };
1952
+ };
1953
+ this.handleNotEquals = (op)=>{
1954
+ if (op.field.includes('.')) {
1955
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
1956
+ return buildNestedGQLFilter(op.field, {
1957
+ '!=': {
1958
+ [leafField]: op.operand
1959
+ }
1951
1960
  });
1952
- cohortsAdapter.addOne(state, defaultCohort);
1953
- state.currentCohortId = defaultCohort.id;
1954
- if (action?.payload.shouldShowMessage) {
1955
- state.message = [
1956
- `deleteCohort|${removedCohortName}|${state.currentCohortId}`
1957
- ];
1958
- }
1959
- return;
1960
1961
  }
1961
- cohortsAdapter.removeOne(state, cohortId);
1962
- // deleted the current cohort so set to the most recent cohort
1963
- if (state.currentCohortId === cohortId) {
1964
- const remainingIds = Object.keys(state.entities);
1965
- state.currentCohortId = remainingIds[0];
1962
+ return {
1963
+ '!=': {
1964
+ [op.field]: op.operand
1965
+ }
1966
+ };
1967
+ };
1968
+ this.handleLessThan = (op)=>{
1969
+ if (op.field.includes('.')) {
1970
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
1971
+ return buildNestedGQLFilter(op.field, {
1972
+ '<': {
1973
+ [leafField]: op.operand
1974
+ }
1975
+ });
1966
1976
  }
1967
- if (action?.payload.shouldShowMessage) {
1968
- state.message = [
1969
- `deleteCohort|${removedCohortName}|${state.currentCohortId}`
1970
- ];
1977
+ return {
1978
+ '<': {
1979
+ [op.field]: op.operand
1980
+ }
1981
+ };
1982
+ };
1983
+ this.handleLessThanOrEquals = (op)=>{
1984
+ if (op.field.includes('.')) {
1985
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
1986
+ return buildNestedGQLFilter(op.field, {
1987
+ '<=': {
1988
+ [leafField]: op.operand
1989
+ }
1990
+ });
1971
1991
  }
1972
- },
1973
- // adds a filter to the cohort filter set at the given index
1974
- updateCohortFilter: (state, action)=>{
1975
- const { index, field, filter } = action.payload;
1976
- const currentCohortId = getCurrentCohortId(state);
1977
- if (!state.entities[currentCohortId]) {
1978
- return;
1992
+ return {
1993
+ '<=': {
1994
+ [op.field]: op.operand
1995
+ }
1996
+ };
1997
+ };
1998
+ this.handleGreaterThan = (op)=>{
1999
+ if (op.field.includes('.')) {
2000
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
2001
+ return buildNestedGQLFilter(op.field, {
2002
+ '>': {
2003
+ [leafField]: op.operand
2004
+ }
2005
+ });
1979
2006
  }
1980
- cohortsAdapter.updateOne(state, {
1981
- id: currentCohortId,
1982
- changes: {
1983
- filters: {
1984
- ...state.entities[currentCohortId].filters,
1985
- [index]: {
1986
- mode: state.entities[currentCohortId]?.filters[index]?.mode ?? 'and',
1987
- root: {
1988
- ...state.entities[currentCohortId]?.filters[index]?.root ?? {},
1989
- [field]: filter
1990
- }
1991
- }
1992
- },
1993
- modified: true,
1994
- modifiedDatetime: new Date().toISOString()
2007
+ return {
2008
+ '>': {
2009
+ [op.field]: op.operand
1995
2010
  }
1996
- });
1997
- },
1998
- setCohortFilter: (state, action)=>{
1999
- const { index, filters } = action.payload;
2000
- const currentCohortId = getCurrentCohortId(state);
2001
- if (!state.entities[currentCohortId]) {
2002
- console.error(`no cohort with id=${currentCohortId} defined`);
2003
- return;
2011
+ };
2012
+ };
2013
+ this.handleGreaterThanOrEquals = (op)=>{
2014
+ if (op.field.includes('.')) {
2015
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
2016
+ return buildNestedGQLFilter(op.field, {
2017
+ '>=': {
2018
+ [leafField]: op.operand
2019
+ }
2020
+ });
2004
2021
  }
2005
- cohortsAdapter.updateOne(state, {
2006
- id: currentCohortId,
2007
- changes: {
2008
- filters: {
2009
- ...state.entities[currentCohortId].filters,
2010
- [index]: filters
2011
- },
2012
- modified: true,
2013
- modifiedDatetime: new Date().toISOString()
2022
+ return {
2023
+ '>=': {
2024
+ [op.field]: op.operand
2014
2025
  }
2015
- });
2016
- },
2017
- setCohortIndexFilters: (state, action)=>{
2018
- const currentCohortId = getCurrentCohortId(state);
2019
- if (!state.entities[currentCohortId]) {
2020
- console.error(`no cohort with id=${currentCohortId} defined`);
2021
- return;
2026
+ };
2027
+ };
2028
+ this.handleIncludes = (op)=>{
2029
+ if (op.field.includes('.')) {
2030
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
2031
+ return buildNestedGQLFilter(op.field, {
2032
+ in: {
2033
+ [leafField]: op.operands
2034
+ }
2035
+ });
2022
2036
  }
2023
- cohortsAdapter.updateOne(state, {
2024
- id: currentCohortId,
2025
- changes: {
2026
- filters: action.payload.filters,
2027
- modified: true,
2028
- modifiedDatetime: new Date().toISOString()
2037
+ return {
2038
+ in: {
2039
+ [op.field]: op.operands
2029
2040
  }
2030
- });
2031
- },
2032
- // removes a filter to the cohort filter set at the given index
2033
- removeCohortFilter: (state, action)=>{
2034
- const { index, field } = action.payload;
2035
- const currentCohortId = getCurrentCohortId(state);
2036
- if (!state.entities[currentCohortId]) {
2037
- console.error(`no cohort with id=${currentCohortId} defined`);
2038
- return;
2041
+ };
2042
+ };
2043
+ this.handleExcludes = (op)=>{
2044
+ if (op.field.includes('.')) {
2045
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
2046
+ return buildNestedGQLFilter(op.field, {
2047
+ exclude: {
2048
+ [leafField]: op.operands
2049
+ }
2050
+ });
2039
2051
  }
2040
- const filters = state.entities[currentCohortId]?.filters[index]?.root;
2041
- if (!filters) {
2042
- return;
2052
+ return {
2053
+ exclude: {
2054
+ [op.field]: op.operands
2055
+ }
2056
+ };
2057
+ };
2058
+ this.handleExcludeIfAny = (op)=>{
2059
+ if (op.field.includes('.')) {
2060
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
2061
+ return buildNestedGQLFilter(op.field, {
2062
+ excludeifany: {
2063
+ [leafField]: op.operands
2064
+ }
2065
+ });
2043
2066
  }
2044
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
2045
- const { [field]: _a, ...updated } = filters;
2046
- cohortsAdapter.updateOne(state, {
2047
- id: currentCohortId,
2048
- changes: {
2049
- filters: {
2050
- ...state.entities[currentCohortId]?.filters,
2051
- [index]: {
2052
- mode: state.entities[currentCohortId].filters[index].mode,
2053
- root: updated
2054
- }
2055
- },
2056
- modified: true,
2057
- modifiedDatetime: new Date().toISOString()
2067
+ return {
2068
+ excludeifany: {
2069
+ [op.field]: op.operands
2058
2070
  }
2071
+ };
2072
+ };
2073
+ this.handleIntersection = (op)=>({
2074
+ and: op.operands.map((x)=>convertFilterToGqlFilter(x))
2059
2075
  });
2060
- },
2061
- duplicateCohort: (state)=>{
2062
- const currentCohortId = getCurrentCohortId(state);
2063
- const currentCohort = state.entities[currentCohortId];
2064
- const newName = generateUniqueName(Object.values(state.entities), currentCohort.name);
2065
- const duplicatedCohort = newCohort({
2066
- filters: {
2067
- ...currentCohort.filters
2068
- },
2069
- customName: newName
2070
- });
2071
- cohortsAdapter.addOne(state, {
2072
- ...duplicatedCohort,
2073
- counts: {
2074
- ...currentCohort.counts
2075
- }
2076
+ this.handleUnion = (op)=>({
2077
+ or: op.operands.map((x)=>convertFilterToGqlFilter(x))
2076
2078
  });
2077
- state.currentCohortId = duplicatedCohort.id;
2078
- },
2079
- // removes all filters from the cohort filter set at the given index
2080
- clearCohortFilters: (state, action)=>{
2081
- const { index } = action.payload;
2082
- const currentCohortId = getCurrentCohortId(state);
2083
- if (!state.entities[currentCohortId]) {
2084
- console.error(`no cohort with id=${currentCohortId} defined`);
2085
- return;
2086
- }
2087
- const filters = state.entities[currentCohortId]?.filters[index]?.root;
2088
- if (!filters) {
2089
- return;
2079
+ this.handleMissing = (op)=>{
2080
+ if (op.field.includes('.')) {
2081
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
2082
+ return buildNestedGQLFilter(op.field, {
2083
+ is: {
2084
+ [leafField]: 'MISSING'
2085
+ }
2086
+ });
2090
2087
  }
2091
- cohortsAdapter.updateOne(state, {
2092
- id: currentCohortId,
2093
- changes: {
2094
- filters: {
2095
- ...state.entities[currentCohortId]?.filters,
2096
- [index]: {
2097
- mode: 'and',
2098
- root: {}
2099
- }
2100
- },
2101
- modified: true,
2102
- modifiedDatetime: new Date().toISOString()
2088
+ return {
2089
+ is: {
2090
+ [op.field]: 'MISSING'
2103
2091
  }
2104
- });
2105
- },
2106
- updateCohortCounts: (state, action)=>{
2107
- const currentCohortId = getCurrentCohortId(state);
2108
- const currentCohort = state.entities[currentCohortId];
2109
- cohortsAdapter.updateOne(state, {
2110
- id: currentCohortId,
2111
- changes: {
2112
- counts: {
2113
- ...currentCohort.counts,
2114
- ...action.payload
2092
+ };
2093
+ };
2094
+ this.handleExists = (op)=>{
2095
+ if (op.field.includes('.')) {
2096
+ const leafField = op.field.split('.').at(-1) ?? 'unset';
2097
+ return buildNestedGQLFilter(op.field, {
2098
+ not: {
2099
+ [leafField]: op?.operand ?? null
2115
2100
  }
2101
+ });
2102
+ }
2103
+ return {
2104
+ not: {
2105
+ [op.field]: op?.operand ?? null
2116
2106
  }
2117
- });
2118
- },
2119
- updateCohortIndexCountById: (state, action)=>{
2120
- const { index, cohortId, counts } = action.payload;
2121
- const cohort = state.entities[cohortId];
2122
- cohortsAdapter.updateOne(state, {
2123
- id: cohortId,
2124
- changes: {
2125
- counts: {
2126
- ...cohort.counts,
2127
- ...{
2128
- [index]: counts
2129
- }
2130
- }
2107
+ };
2108
+ };
2109
+ this.handleNestedFilter = (op)=>{
2110
+ const child = convertFilterToGqlFilter(op.operand);
2111
+ return {
2112
+ nested: {
2113
+ path: op.path,
2114
+ ...child
2131
2115
  }
2132
- });
2133
- },
2134
- setCurrentCohortId: (state, action)=>{
2135
- state.currentCohortId = action.payload;
2136
- },
2137
- /** @hidden */ setCohortList: (state, action)=>{
2138
- if (!action.payload) {
2139
- cohortsAdapter.removeMany(state, state.ids);
2140
- } else {
2141
- cohortsAdapter.upsertMany(state, [
2142
- ...action.payload
2143
- ]);
2144
- }
2145
- }
2116
+ };
2117
+ };
2146
2118
  }
2147
- });
2119
+ }
2120
+ const convertFilterToNestedGqlFilter = (filter)=>{
2121
+ const handler = new ToGqlAllNested();
2122
+ return handleOperation(handler, filter);
2123
+ };
2124
+ const convertFilterSetToNestedGqlFilter = (fs, toplevelOp = 'and')=>{
2125
+ const fsKeys = Object.keys(fs.root);
2126
+ // if no keys return undefined
2127
+ if (fsKeys.length === 0) return {
2128
+ and: []
2129
+ };
2130
+ return toplevelOp === 'and' ? {
2131
+ and: fsKeys.map((key)=>convertFilterToNestedGqlFilter(fs.root[key]))
2132
+ } : {
2133
+ or: fsKeys.map((key)=>convertFilterToNestedGqlFilter(fs.root[key]))
2134
+ };
2135
+ };
2136
+
2137
+ const defaultCohortNameGenerator = ()=>`Custom cohort ${new Date().toLocaleString('en-CA', {
2138
+ timeZone: 'America/Chicago',
2139
+ hour12: false
2140
+ }).replace(',', '')}`;
2141
+ const isNameUnique = (entities, name, excludeId)=>{
2142
+ const trimmedName = name.trim();
2143
+ if (!trimmedName) return false;
2144
+ return !entities.some((cohort)=>cohort && cohort.id !== excludeId && cohort.name.trim().toLowerCase() === trimmedName.toLowerCase());
2145
+ };
2146
+ const generateUniqueName = (entities, baseName)=>{
2147
+ const trimmedBaseName = baseName.trim();
2148
+ // If base name is unique, use it
2149
+ if (isNameUnique(entities, trimmedBaseName)) {
2150
+ return trimmedBaseName;
2151
+ }
2152
+ // Find a unique name by appending numbers
2153
+ let counter = 1;
2154
+ let uniqueName;
2155
+ do {
2156
+ uniqueName = `${trimmedBaseName} (${counter})`;
2157
+ counter++;
2158
+ }while (!isNameUnique(entities, uniqueName))
2159
+ return uniqueName;
2160
+ };
2148
2161
  /**
2149
- * Returns the selectors for the cohorts EntityAdapter
2150
- * @param state - the CoreState
2162
+ * This function takes a FilterSet object and a prefix string as input.
2163
+ * It filters the root property of the FilterSet object and returns a
2164
+ * new FilterSet object that only contains filters with field names
2165
+ * that start with the specified prefix.
2151
2166
  *
2152
- * @hidden
2153
- */ const cohortSelectors = cohortsAdapter.getSelectors((state)=>state.cohorts.cohortManager);
2154
- // Filter actions: addFilter, removeFilter, updateFilter
2155
- const { createNewCohort, updateCohortFilter, setCohortFilter, setCohortIndexFilters, duplicateCohort, removeCohortFilter, clearCohortFilters, removeCohort, setCurrentCohortId, updateCohortName, updateCohortCounts, updateCohortIndexCountById, setCohortList } = cohortManagerSlice.actions;
2156
- const cohortReducer = cohortManagerSlice.reducer;
2157
-
2158
- const initialState$2 = {};
2159
- const expandSlice$1 = toolkit.createSlice({
2160
- name: 'CohortBuilder/filterExpand',
2161
- initialState: initialState$2,
2162
- reducers: {
2163
- toggleCohortBuilderCategoryFilter: (state, action)=>{
2164
- return {
2165
- ...state,
2166
- [action.payload.index]: {
2167
- ...state[action.payload.index],
2168
- [action.payload.field]: action.payload.expanded
2169
- }
2170
- };
2171
- },
2172
- toggleCohortBuilderAllFilters: (state, action)=>{
2173
- return {
2174
- ...state,
2175
- [action.payload.index]: Object.keys(state[action.payload.index]).reduce((acc, k)=>{
2176
- acc[k] = action.payload.expand;
2177
- return acc;
2178
- }, {})
2179
- };
2180
- }
2167
+ * @param fs - The FilterSet object to filter
2168
+ * @param prefix - The prefix to filter by
2169
+ * @returns - A new FilterSet object that only contains filters with field names that start with the specified prefix
2170
+ * @category Filters
2171
+ */ const extractFiltersWithPrefixFromFilterSet = (fs, prefix)=>{
2172
+ if (fs === undefined || fs.root === undefined) {
2173
+ return {
2174
+ mode: 'and',
2175
+ root: {}
2176
+ };
2181
2177
  }
2182
- });
2183
- const cohortBuilderFiltersExpandedReducer = expandSlice$1.reducer;
2184
- const { toggleCohortBuilderCategoryFilter, toggleCohortBuilderAllFilters } = expandSlice$1.actions;
2185
- const selectCohortFilterExpanded = (state, index, field)=>state.cohorts.filtersExpanded?.[index]?.[field];
2186
- const selectAllCohortFiltersCollapsed = (state, index)=>index in state.cohorts.filtersExpanded ? Object.values(state.cohorts.filtersExpanded?.[index]).every((e)=>!e) : false;
2187
-
2188
- const initialState$1 = {};
2189
- const expandSlice = toolkit.createSlice({
2190
- name: 'CohortBuilder/filterCombineMode',
2191
- initialState: initialState$1,
2192
- reducers: {
2193
- setCohortFilterCombineMode: (state, action)=>{
2194
- return {
2195
- ...state,
2196
- [action.payload.index]: {
2197
- ...state[action.payload.index],
2198
- [action.payload.field]: action.payload.mode
2199
- }
2200
- };
2178
+ return Object.values(fs.root).reduce((acc, filter)=>{
2179
+ if (isIntersectionOrUnion(filter) || isNestedFilter(filter)) return acc;
2180
+ if (filter.field.startsWith(prefix)) {
2181
+ acc.root[filter.field] = filter;
2201
2182
  }
2202
- }
2203
- });
2204
- const cohortBuilderFiltersCombineModeReducer = expandSlice.reducer;
2205
- const { setCohortFilterCombineMode } = expandSlice.actions;
2206
- const selectCohortFilterCombineMode = (state, index, field)=>state.cohorts.filtersCombineMode?.[index]?.[field] ?? 'or';
2183
+ return acc;
2184
+ }, {
2185
+ mode: 'and',
2186
+ root: {}
2187
+ });
2188
+ };
2207
2189
 
2208
- const initialState = {
2209
- shouldShareFilters: false,
2210
- sharedFiltersMap: {}
2190
+ /**
2191
+ * Cohorts in Gen3 are defined as a set of filters for each index in the data.
2192
+ * This means one cohort id defined for all "tabs" in CohortBuilder (explorer)
2193
+ * Switching a cohort id means all the cohorts for the index are changed.
2194
+ */ const DEFAULT_COHORT_NAME = 'Cohort';
2195
+ const newCohort = ({ filters = {}, customName })=>{
2196
+ const ts = new Date().toISOString();
2197
+ const newName = customName ?? defaultCohortNameGenerator();
2198
+ const newId = createCohortId();
2199
+ return {
2200
+ name: newName,
2201
+ id: newId,
2202
+ filters: filters ?? {},
2203
+ modified: false,
2204
+ saved: false,
2205
+ createdDatetime: ts,
2206
+ modifiedDatetime: ts,
2207
+ counts: {}
2208
+ };
2211
2209
  };
2212
- const cohortSharedFiltersSlice = toolkit.createSlice({
2213
- name: 'cohortSharedFilters',
2214
- initialState: initialState,
2215
- reducers: {
2216
- setShouldShareFilters: (state, action)=>{
2217
- state.shouldShareFilters = action.payload;
2218
- return state;
2219
- },
2220
- setSharedFilters: (state, action)=>{
2221
- state.sharedFiltersMap = action.payload;
2222
- }
2223
- }
2210
+ const nanoid = nanoid$1.customAlphabet('1234567890abcdef', 16);
2211
+ const createCohortId = ()=>nanoid();
2212
+ const cohortsAdapter = toolkit.createEntityAdapter({
2213
+ sortComparer: (a, b)=>{
2214
+ if (a.modifiedDatetime <= b.modifiedDatetime) return 1;
2215
+ else return -1;
2216
+ },
2217
+ selectId: (cohort)=>cohort.id
2224
2218
  });
2225
- const selectShouldShareFilters = (state)=>state.cohorts.sharedFilters.shouldShareFilters;
2226
- const selectSharedFilters = (state)=>state.cohorts.sharedFilters.sharedFiltersMap;
2227
- const selectSharedFiltersForFields = (state, field)=>state.cohorts.sharedFilters.sharedFiltersMap?.[field] ?? [
2228
- field
2229
- ];
2230
- const { setShouldShareFilters, setSharedFilters } = cohortSharedFiltersSlice.actions;
2231
- const cohortSharedFiltersReducer = cohortSharedFiltersSlice.reducer;
2232
-
2233
- const cohortReducers = toolkit.combineReducers({
2234
- filtersExpanded: cohortBuilderFiltersExpandedReducer,
2235
- filtersCombineMode: cohortBuilderFiltersCombineModeReducer,
2236
- sharedFilters: cohortSharedFiltersReducer,
2237
- cohortManager: cohortReducer
2219
+ // Create an initial unsaved cohort
2220
+ const initialCohort = newCohort({
2221
+ customName: DEFAULT_COHORT_NAME
2238
2222
  });
2239
-
2240
- const rootReducer = toolkit.combineReducers({
2241
- gen3Services: gen3ServicesReducer,
2242
- user: userReducer,
2243
- gen3Apps: gen3AppReducer,
2244
- drsHostnames: drsHostnamesReducer,
2245
- modals: modalReducer,
2246
- cohorts: cohortReducers,
2247
- activeWorkspace: activeWorkspaceReducer,
2248
- [guppyApiSliceReducerPath]: guppyApiReducer,
2249
- [userAuthApiReducerPath]: userAuthApiReducer,
2250
- [cartReducerPath]: cartReducer
2223
+ const emptyInitialState = cohortsAdapter.getInitialState({
2224
+ currentCohortId: initialCohort.id,
2225
+ message: undefined
2251
2226
  });
2252
-
2253
- /**
2254
- * Flattens a deep nested JSON object skipping
2255
- * the first level to avoid potentially flattening
2256
- * non-nested data.
2257
- * @param {JSON} json
2258
- */ function flattenJson(json) {
2259
- const flattenedJson = [];
2260
- Object.keys(json).forEach((key)=>{
2261
- flattenedJson.push(flat.flatten(json[key], {
2262
- delimiter: '_'
2263
- }));
2264
- });
2265
- return flattenedJson;
2266
- }
2267
- /**
2268
- * Converts JSON based on a config.
2269
- * @param {JSON} json
2270
- * @param {Object} config
2271
- */ async function conversion(json, config) {
2272
- return Papa.unparse(json, config);
2273
- }
2227
+ // Set the initial cohort in the adapter state
2228
+ const initialState$3 = cohortsAdapter.setOne(emptyInitialState, initialCohort);
2229
+ const getCurrentCohortId = (state)=>state.currentCohortId;
2274
2230
  /**
2275
- * Converts JSON to a specified file format.
2276
- * Defaults to JSON if file format is not supported.
2277
- * @param {JSON} json
2278
- * @param {string} format
2279
- */ async function jsonToFormat(json, format) {
2280
- if (Object.keys(FILE_DELIMITERS).includes(format)) {
2281
- const flatJson = flattenJson(json);
2282
- const data = await conversion(flatJson, {
2283
- delimiter: FILE_DELIMITERS[format]
2284
- });
2285
- return data;
2286
- }
2287
- return json;
2288
- }
2289
-
2290
- // type guard functions
2291
- const isHistogramRangeData = (key)=>{
2292
- return Array.isArray(key) && key.length === 2 && key.every((item)=>typeof item === 'number');
2293
- };
2294
- const isJSONObject = (data)=>{
2295
- return typeof data === 'object' && data !== null && !Array.isArray(data);
2296
- };
2297
- const isJSONValue = (data)=>{
2298
- return typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean' || Array.isArray(data) && data.every(isJSONValue) || isJSONObject(data);
2299
- };
2300
- const isJSONValueArray = (data)=>{
2301
- return Array.isArray(data) && data.every(isJSONValue);
2302
- };
2303
- const isValidObject = (input)=>typeof input === 'object' && input !== null;
2304
- const isHistogramData = (data)=>{
2305
- return isValidObject(data) && 'key' in data && 'count' in data;
2231
+ * Redux slice for cohort filters
2232
+ */ const cohortManagerSlice = toolkit.createSlice({
2233
+ name: 'cohort',
2234
+ initialState: initialState$3,
2235
+ reducers: {
2236
+ createNewCohort: (state, action)=>{
2237
+ const baseName = action.payload.name || `Cohort`;
2238
+ const uniqueName = generateUniqueName(Object.values(state.entities), baseName);
2239
+ const cohort = newCohort({
2240
+ filters: action.payload.filters,
2241
+ customName: uniqueName
2242
+ });
2243
+ cohortsAdapter.addOne(state, cohort);
2244
+ if (action.payload?.setAsCurrent) {
2245
+ state.currentCohortId = cohort.id;
2246
+ }
2247
+ },
2248
+ updateCohortName: (state, action)=>{
2249
+ const { id, name } = action.payload;
2250
+ cohortsAdapter.updateOne(state, {
2251
+ id: id,
2252
+ changes: {
2253
+ name: name,
2254
+ modified: true,
2255
+ modifiedDatetime: new Date().toISOString()
2256
+ }
2257
+ });
2258
+ },
2259
+ removeCohort: (state, action)=>{
2260
+ const { id: cohortId } = action.payload;
2261
+ const removedCohortName = state.entities[cohortId].name;
2262
+ const totalCohorts = Object.keys(state.entities).length;
2263
+ if (totalCohorts <= 1) {
2264
+ cohortsAdapter.removeAll(state);
2265
+ const defaultCohort = newCohort({
2266
+ filters: {},
2267
+ customName: DEFAULT_COHORT_NAME
2268
+ });
2269
+ cohortsAdapter.addOne(state, defaultCohort);
2270
+ state.currentCohortId = defaultCohort.id;
2271
+ if (action?.payload.shouldShowMessage) {
2272
+ state.message = [
2273
+ `deleteCohort|${removedCohortName}|${state.currentCohortId}`
2274
+ ];
2275
+ }
2276
+ return;
2277
+ }
2278
+ cohortsAdapter.removeOne(state, cohortId);
2279
+ // deleted the current cohort so set to the most recent cohort
2280
+ if (state.currentCohortId === cohortId) {
2281
+ const remainingIds = Object.keys(state.entities);
2282
+ state.currentCohortId = remainingIds[0];
2283
+ }
2284
+ if (action?.payload.shouldShowMessage) {
2285
+ state.message = [
2286
+ `deleteCohort|${removedCohortName}|${state.currentCohortId}`
2287
+ ];
2288
+ }
2289
+ },
2290
+ // adds a filter to the cohort filter set at the given index
2291
+ updateCohortFilter: (state, action)=>{
2292
+ const { index, field, filter } = action.payload;
2293
+ const currentCohortId = getCurrentCohortId(state);
2294
+ if (!state.entities[currentCohortId]) {
2295
+ return;
2296
+ }
2297
+ cohortsAdapter.updateOne(state, {
2298
+ id: currentCohortId,
2299
+ changes: {
2300
+ filters: {
2301
+ ...state.entities[currentCohortId].filters,
2302
+ [index]: {
2303
+ mode: state.entities[currentCohortId]?.filters[index]?.mode ?? 'and',
2304
+ root: {
2305
+ ...state.entities[currentCohortId]?.filters[index]?.root ?? {},
2306
+ [field]: filter
2307
+ }
2308
+ }
2309
+ },
2310
+ modified: true,
2311
+ modifiedDatetime: new Date().toISOString()
2312
+ }
2313
+ });
2314
+ },
2315
+ setCohortFilter: (state, action)=>{
2316
+ const { index, filters } = action.payload;
2317
+ const currentCohortId = getCurrentCohortId(state);
2318
+ if (!state.entities[currentCohortId]) {
2319
+ console.error(`no cohort with id=${currentCohortId} defined`);
2320
+ return;
2321
+ }
2322
+ cohortsAdapter.updateOne(state, {
2323
+ id: currentCohortId,
2324
+ changes: {
2325
+ filters: {
2326
+ ...state.entities[currentCohortId].filters,
2327
+ [index]: filters
2328
+ },
2329
+ modified: true,
2330
+ modifiedDatetime: new Date().toISOString()
2331
+ }
2332
+ });
2333
+ },
2334
+ setCohortIndexFilters: (state, action)=>{
2335
+ const currentCohortId = getCurrentCohortId(state);
2336
+ if (!state.entities[currentCohortId]) {
2337
+ console.error(`no cohort with id=${currentCohortId} defined`);
2338
+ return;
2339
+ }
2340
+ cohortsAdapter.updateOne(state, {
2341
+ id: currentCohortId,
2342
+ changes: {
2343
+ filters: action.payload.filters,
2344
+ modified: true,
2345
+ modifiedDatetime: new Date().toISOString()
2346
+ }
2347
+ });
2348
+ },
2349
+ // removes a filter to the cohort filter set at the given index
2350
+ removeCohortFilter: (state, action)=>{
2351
+ const { index, field } = action.payload;
2352
+ const currentCohortId = getCurrentCohortId(state);
2353
+ if (!state.entities[currentCohortId]) {
2354
+ console.error(`no cohort with id=${currentCohortId} defined`);
2355
+ return;
2356
+ }
2357
+ const filters = state.entities[currentCohortId]?.filters[index]?.root;
2358
+ if (!filters) {
2359
+ return;
2360
+ }
2361
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
2362
+ const { [field]: _a, ...updated } = filters;
2363
+ cohortsAdapter.updateOne(state, {
2364
+ id: currentCohortId,
2365
+ changes: {
2366
+ filters: {
2367
+ ...state.entities[currentCohortId]?.filters,
2368
+ [index]: {
2369
+ mode: state.entities[currentCohortId].filters[index].mode,
2370
+ root: updated
2371
+ }
2372
+ },
2373
+ modified: true,
2374
+ modifiedDatetime: new Date().toISOString()
2375
+ }
2376
+ });
2377
+ },
2378
+ duplicateCohort: (state)=>{
2379
+ const currentCohortId = getCurrentCohortId(state);
2380
+ const currentCohort = state.entities[currentCohortId];
2381
+ const newName = generateUniqueName(Object.values(state.entities), currentCohort.name);
2382
+ const duplicatedCohort = newCohort({
2383
+ filters: {
2384
+ ...currentCohort.filters
2385
+ },
2386
+ customName: newName
2387
+ });
2388
+ cohortsAdapter.addOne(state, {
2389
+ ...duplicatedCohort,
2390
+ counts: {
2391
+ ...currentCohort.counts
2392
+ }
2393
+ });
2394
+ state.currentCohortId = duplicatedCohort.id;
2395
+ },
2396
+ // removes all filters from the cohort filter set at the given index
2397
+ clearCohortFilters: (state, action)=>{
2398
+ const { index } = action.payload;
2399
+ const currentCohortId = getCurrentCohortId(state);
2400
+ if (!state.entities[currentCohortId]) {
2401
+ console.error(`no cohort with id=${currentCohortId} defined`);
2402
+ return;
2403
+ }
2404
+ const filters = state.entities[currentCohortId]?.filters[index]?.root;
2405
+ if (!filters) {
2406
+ return;
2407
+ }
2408
+ cohortsAdapter.updateOne(state, {
2409
+ id: currentCohortId,
2410
+ changes: {
2411
+ filters: {
2412
+ ...state.entities[currentCohortId]?.filters,
2413
+ [index]: {
2414
+ mode: 'and',
2415
+ root: {}
2416
+ }
2417
+ },
2418
+ modified: true,
2419
+ modifiedDatetime: new Date().toISOString()
2420
+ }
2421
+ });
2422
+ },
2423
+ updateCohortCounts: (state, action)=>{
2424
+ const currentCohortId = getCurrentCohortId(state);
2425
+ const currentCohort = state.entities[currentCohortId];
2426
+ cohortsAdapter.updateOne(state, {
2427
+ id: currentCohortId,
2428
+ changes: {
2429
+ counts: {
2430
+ ...currentCohort.counts,
2431
+ ...action.payload
2432
+ }
2433
+ }
2434
+ });
2435
+ },
2436
+ updateCohortIndexCountById: (state, action)=>{
2437
+ const { index, cohortId, counts } = action.payload;
2438
+ const cohort = state.entities[cohortId];
2439
+ cohortsAdapter.updateOne(state, {
2440
+ id: cohortId,
2441
+ changes: {
2442
+ counts: {
2443
+ ...cohort.counts,
2444
+ ...{
2445
+ [index]: counts
2446
+ }
2447
+ }
2448
+ }
2449
+ });
2450
+ },
2451
+ setCurrentCohortId: (state, action)=>{
2452
+ state.currentCohortId = action.payload;
2453
+ },
2454
+ /** @hidden */ setCohortList: (state, action)=>{
2455
+ if (!action.payload) {
2456
+ cohortsAdapter.removeMany(state, state.ids);
2457
+ } else {
2458
+ cohortsAdapter.upsertMany(state, [
2459
+ ...action.payload
2460
+ ]);
2461
+ }
2462
+ }
2463
+ }
2464
+ });
2465
+ /**
2466
+ * Returns the selectors for the cohorts EntityAdapter
2467
+ * @param state - the CoreState
2468
+ *
2469
+ * @hidden
2470
+ */ const cohortSelectors = cohortsAdapter.getSelectors((state)=>state.cohorts.cohortManager);
2471
+ // Filter actions: addFilter, removeFilter, updateFilter
2472
+ const { createNewCohort, updateCohortFilter, setCohortFilter, setCohortIndexFilters, duplicateCohort, removeCohortFilter, clearCohortFilters, removeCohort, setCurrentCohortId, updateCohortName, updateCohortCounts, updateCohortIndexCountById, setCohortList } = cohortManagerSlice.actions;
2473
+ const cohortReducer = cohortManagerSlice.reducer;
2474
+
2475
+ const initialState$2 = {};
2476
+ const expandSlice$1 = toolkit.createSlice({
2477
+ name: 'CohortBuilder/filterExpand',
2478
+ initialState: initialState$2,
2479
+ reducers: {
2480
+ toggleCohortBuilderCategoryFilter: (state, action)=>{
2481
+ return {
2482
+ ...state,
2483
+ [action.payload.index]: {
2484
+ ...state[action.payload.index],
2485
+ [action.payload.field]: action.payload.expanded
2486
+ }
2487
+ };
2488
+ },
2489
+ toggleCohortBuilderAllFilters: (state, action)=>{
2490
+ return {
2491
+ ...state,
2492
+ [action.payload.index]: Object.keys(state[action.payload.index]).reduce((acc, k)=>{
2493
+ acc[k] = action.payload.expand;
2494
+ return acc;
2495
+ }, {})
2496
+ };
2497
+ }
2498
+ }
2499
+ });
2500
+ const cohortBuilderFiltersExpandedReducer = expandSlice$1.reducer;
2501
+ const { toggleCohortBuilderCategoryFilter, toggleCohortBuilderAllFilters } = expandSlice$1.actions;
2502
+ const selectCohortFilterExpanded = (state, index, field)=>state.cohorts.filtersExpanded?.[index]?.[field];
2503
+ const selectAllCohortFiltersCollapsed = (state, index)=>index in state.cohorts.filtersExpanded ? Object.values(state.cohorts.filtersExpanded?.[index]).every((e)=>!e) : false;
2504
+
2505
+ const initialState$1 = {};
2506
+ const expandSlice = toolkit.createSlice({
2507
+ name: 'CohortBuilder/filterCombineMode',
2508
+ initialState: initialState$1,
2509
+ reducers: {
2510
+ setCohortFilterCombineMode: (state, action)=>{
2511
+ return {
2512
+ ...state,
2513
+ [action.payload.index]: {
2514
+ ...state[action.payload.index],
2515
+ [action.payload.field]: action.payload.mode
2516
+ }
2517
+ };
2518
+ }
2519
+ }
2520
+ });
2521
+ const cohortBuilderFiltersCombineModeReducer = expandSlice.reducer;
2522
+ const { setCohortFilterCombineMode } = expandSlice.actions;
2523
+ const selectCohortFilterCombineMode = (state, index, field)=>state.cohorts.filtersCombineMode?.[index]?.[field] ?? 'or';
2524
+
2525
+ const initialState = {
2526
+ shouldShareFilters: false,
2527
+ sharedFiltersMap: {}
2528
+ };
2529
+ const cohortSharedFiltersSlice = toolkit.createSlice({
2530
+ name: 'cohortSharedFilters',
2531
+ initialState: initialState,
2532
+ reducers: {
2533
+ setShouldShareFilters: (state, action)=>{
2534
+ state.shouldShareFilters = action.payload;
2535
+ return state;
2536
+ },
2537
+ setSharedFilters: (state, action)=>{
2538
+ state.sharedFiltersMap = action.payload;
2539
+ }
2540
+ }
2541
+ });
2542
+ const selectShouldShareFilters = (state)=>state.cohorts.sharedFilters.shouldShareFilters;
2543
+ const selectSharedFilters = (state)=>state.cohorts.sharedFilters.sharedFiltersMap;
2544
+ const selectSharedFiltersForFields = (state, field)=>state.cohorts.sharedFilters.sharedFiltersMap?.[field] ?? [
2545
+ field
2546
+ ];
2547
+ const { setShouldShareFilters, setSharedFilters } = cohortSharedFiltersSlice.actions;
2548
+ const cohortSharedFiltersReducer = cohortSharedFiltersSlice.reducer;
2549
+
2550
+ const cohortReducers = toolkit.combineReducers({
2551
+ filtersExpanded: cohortBuilderFiltersExpandedReducer,
2552
+ filtersCombineMode: cohortBuilderFiltersCombineModeReducer,
2553
+ sharedFilters: cohortSharedFiltersReducer,
2554
+ cohortManager: cohortReducer
2555
+ });
2556
+
2557
+ const rootReducer = toolkit.combineReducers({
2558
+ gen3Services: gen3ServicesReducer,
2559
+ user: userReducer,
2560
+ gen3Apps: gen3AppReducer,
2561
+ drsHostnames: drsHostnamesReducer,
2562
+ modals: modalReducer,
2563
+ cohorts: cohortReducers,
2564
+ activeWorkspace: activeWorkspaceReducer,
2565
+ [guppyApiSliceReducerPath]: guppyApiReducer,
2566
+ [userAuthApiReducerPath]: userAuthApiReducer,
2567
+ [cartReducerPath]: cartReducer
2568
+ });
2569
+
2570
+ /**
2571
+ * Flattens a deep nested JSON object skipping
2572
+ * the first level to avoid potentially flattening
2573
+ * non-nested data.
2574
+ * @param {JSON} json
2575
+ */ function flattenJson(json) {
2576
+ const flattenedJson = [];
2577
+ Object.keys(json).forEach((key)=>{
2578
+ flattenedJson.push(flat.flatten(json[key], {
2579
+ delimiter: '_'
2580
+ }));
2581
+ });
2582
+ return flattenedJson;
2583
+ }
2584
+ /**
2585
+ * Converts JSON based on a config.
2586
+ * @param {JSON} json
2587
+ * @param {Object} config
2588
+ */ async function conversion(json, config) {
2589
+ return Papa.unparse(json, config);
2590
+ }
2591
+ /**
2592
+ * Converts JSON to a specified file format.
2593
+ * Defaults to JSON if file format is not supported.
2594
+ * @param {JSON} json
2595
+ * @param {string} format
2596
+ */ async function jsonToFormat(json, format) {
2597
+ if (Object.keys(FILE_DELIMITERS).includes(format)) {
2598
+ const flatJson = flattenJson(json);
2599
+ const data = await conversion(flatJson, {
2600
+ delimiter: FILE_DELIMITERS[format]
2601
+ });
2602
+ return data;
2603
+ }
2604
+ return json;
2605
+ }
2606
+
2607
+ // type guard functions
2608
+ const isHistogramRangeData = (key)=>{
2609
+ return Array.isArray(key) && key.length === 2 && key.every((item)=>typeof item === 'number');
2610
+ };
2611
+ const isJSONObject = (data)=>{
2612
+ return typeof data === 'object' && data !== null && !Array.isArray(data);
2613
+ };
2614
+ const isJSONValue = (data)=>{
2615
+ return typeof data === 'string' || typeof data === 'number' || typeof data === 'boolean' || Array.isArray(data) && data.every(isJSONValue) || isJSONObject(data);
2616
+ };
2617
+ const isJSONValueArray = (data)=>{
2618
+ return Array.isArray(data) && data.every(isJSONValue);
2619
+ };
2620
+ const isValidObject = (input)=>typeof input === 'object' && input !== null;
2621
+ const isHistogramData = (data)=>{
2622
+ return isValidObject(data) && 'key' in data && 'count' in data;
2306
2623
  };
2307
2624
  const isHistogramDataArray = (input)=>{
2308
2625
  if (!isValidObject(input) || !Array.isArray(input.histogram)) {
@@ -2341,10 +2658,8 @@ const isStatsValue = (item)=>{
2341
2658
  'stddev',
2342
2659
  'median'
2343
2660
  ];
2344
- for (const field of numericFields){
2345
- if (field in obj && typeof obj[field] !== 'number') {
2346
- return false;
2347
- }
2661
+ if (!numericFields.some((field)=>field in obj && typeof obj[field] !== 'number')) {
2662
+ return false;
2348
2663
  }
2349
2664
  // Check percentiles structure if present
2350
2665
  if ('percentiles' in obj) {
@@ -2352,17 +2667,6 @@ const isStatsValue = (item)=>{
2352
2667
  if (typeof percentiles !== 'object' || percentiles === null) {
2353
2668
  return false;
2354
2669
  }
2355
- const pObj = percentiles;
2356
- const requiredPercentiles = [
2357
- 'p25',
2358
- 'p50',
2359
- 'p75'
2360
- ];
2361
- for (const p of requiredPercentiles){
2362
- if (p in pObj && typeof pObj[p] !== 'number') {
2363
- return false;
2364
- }
2365
- }
2366
2670
  }
2367
2671
  return true;
2368
2672
  };
@@ -2607,443 +2911,168 @@ const groupSharedFields = (data)=>{
2607
2911
  x.count = x.count < minValue ? -1 : x.count;
2608
2912
  });
2609
2913
  });
2610
- return data;
2611
- };
2612
-
2613
- const customQueryStrForField = (field, query, depth = 0)=>{
2614
- const indent = ' '.repeat(depth);
2615
- const splittedFieldArray = field.split('.');
2616
- const splittedField = splittedFieldArray.shift();
2617
- if (splittedFieldArray.length === 0) {
2618
- return `${indent}${splittedField} ${query}`;
2619
- }
2620
- return `${indent}${splittedField} {
2621
- ${customQueryStrForField(splittedFieldArray.join('.'), query, depth + 1)}
2622
- ${indent}}`;
2623
- };
2624
- // TODO: refactor the function below using customQueryStrForEachField and a wrapper function that passes the query
2625
- const histogramQueryStrForEachField = (field)=>{
2626
- const splittedFieldArray = field.split('.');
2627
- const splittedField = splittedFieldArray.shift();
2628
- if (splittedFieldArray.length === 0) {
2629
- return `
2630
- ${splittedField} {
2631
- histogram {
2632
- key
2633
- count
2634
- }
2635
- }`;
2636
- }
2637
- return `
2638
- ${splittedField} {
2639
- ${histogramQueryStrForEachField(splittedFieldArray.join('.'))}
2640
- }`;
2641
- };
2642
- const statsQueryStrForEachField = (field)=>{
2643
- const splittedFieldArray = field.split('.');
2644
- const splittedField = splittedFieldArray.shift();
2645
- if (splittedFieldArray.length === 0) {
2646
- return `
2647
- ${splittedField} {
2648
- histogram {
2649
- count
2650
- min
2651
- max
2652
- avg
2653
- sum
2654
- }
2655
- }`;
2656
- }
2657
- return `
2658
- ${splittedField} {
2659
- ${statsQueryStrForEachField(splittedFieldArray.join('.'))}
2660
- }`;
2661
- };
2662
- const nestedHistogramQueryStrForEachField = (mainField, numericAggAsText)=>`
2663
- ${mainField} {
2664
- ${numericAggAsText ? 'asTextHistogram' : 'histogram'} {
2665
- key
2666
- count
2667
- missingFields {
2668
- field
2669
- count
2670
- }
2671
- termsFields {
2672
- field
2673
- count
2674
- terms {
2675
- key
2676
- count
2677
- }
2678
- }
2679
- }
2680
- }`;
2681
- const rawDataQueryStrForEachField$1 = (field)=>{
2682
- const splitFieldArray = field.split('.');
2683
- const splitField = splitFieldArray.shift();
2684
- if (splitFieldArray.length === 0) {
2685
- return `
2686
- ${splitField}
2687
- `;
2688
- }
2689
- return `
2690
- ${splitField} {
2691
- ${rawDataQueryStrForEachField$1(splitFieldArray.join('.'))}
2692
- }`;
2693
- };
2694
-
2695
- const convertNumericFromToArrayToFilters = (field, range, isNested = true)=>{
2696
- const { from, to } = range;
2697
- return {
2698
- operator: 'and',
2699
- operands: [
2700
- isNested ? buildNestedFilterForOperation(field, {
2701
- operator: '>=',
2702
- field,
2703
- operand: from
2704
- }) : {
2705
- operator: '>=',
2706
- field,
2707
- operand: from
2708
- },
2709
- isNested ? buildNestedFilterForOperation(field, {
2710
- operator: '<',
2711
- field,
2712
- operand: to
2713
- }) : {
2714
- operator: '<',
2715
- field,
2716
- operand: to
2717
- }
2718
- ]
2719
- };
2720
- };
2721
- const rawDataQueryStrForEachField = (field, asTextHistogram = false)=>{
2722
- const splitFieldArray = field.split('.');
2723
- const splitField = splitFieldArray.shift();
2724
- let middleQuery = '';
2725
- if (splitFieldArray.length === 0) {
2726
- middleQuery = `${splitField} { ${asTextHistogram ? 'histogram: asTextHistogram' : 'histogram'} { count } }`;
2727
- } else {
2728
- middleQuery = `${splitField} { ${rawDataQueryStrForEachField(splitFieldArray.join('.'), asTextHistogram)} }`;
2729
- }
2730
- return middleQuery;
2731
- };
2732
- const buildAliasedNestedCountsQuery = ({ type, field, rangeName, asTextHistogram = false })=>{
2733
- const dataParams = [
2734
- `filter: $${rangeName}`
2735
- ];
2736
- const dataTypeLine = `${rangeName} : ${type} (accessibility: $accessibility ${dataParams}) {`;
2737
- const processedFields = rawDataQueryStrForEachField(field, asTextHistogram);
2738
- return `${dataTypeLine} ${processedFields} }`;
2739
- };
2740
- const buildRangeFilters = (field, ranges, filters, rangeBaseName, isNested = true)=>{
2741
- return Object.entries(ranges).reduce((acc, [, rangeValue], idx)=>{
2742
- acc[`${rangeBaseName}_${idx}`] = {
2743
- mode: filters.mode,
2744
- root: {
2745
- ...filters.root,
2746
- [field]: convertNumericFromToArrayToFilters(field, rangeValue, isNested)
2747
- }
2748
- };
2749
- return acc;
2750
- }, {});
2751
- };
2752
- const buildRangeQuery = (field, ranges, filters, rangeBaseName = 'range', index = 'cases', indexPrefix = '', isNested = true, asTextHistogram = false)=>{
2753
- const rangeFilters = buildRangeFilters(field, ranges, filters, rangeBaseName, isNested);
2754
- let query = `query rangeQuery ($accessibility: Accessibility, ${Object.keys(rangeFilters).map((rangeKey)=>`$${rangeKey}: JSON`).join(',')} ) { ${indexPrefix}_aggregation {`;
2755
- Object.keys(rangeFilters).forEach((rangeKey)=>{
2756
- const rangeQuery = buildAliasedNestedCountsQuery({
2757
- type: index,
2758
- field,
2759
- rangeName: rangeKey,
2760
- asTextHistogram
2761
- });
2762
- query += rangeQuery + ' \n';
2763
- });
2764
- query += `}}`;
2765
- return {
2766
- query: query,
2767
- filters: rangeFilters
2768
- };
2769
- };
2770
-
2771
- const { selectAll: selectAllCohorts, selectTotal: selectTotalCohorts, selectById: selectCohortById, selectIds: selectCohortIds } = cohortsAdapter.getSelectors((state)=>state.cohorts.cohortManager);
2772
- /**
2773
- * Internally used selector for the exported selectora
2774
- * @param state
2775
- */ const getCurrentCohortFromCoreState = (state)=>{
2776
- return state.cohorts.cohortManager.currentCohortId;
2777
- };
2778
- const selectCohortFilters = (state)=>{
2779
- const currentCohortId = getCurrentCohortFromCoreState(state);
2780
- return state.cohorts.cohortManager.entities[currentCohortId]?.filters;
2781
- };
2782
- const selectCurrentCohortFilters = (state)=>{
2783
- const currentCohortId = getCurrentCohortFromCoreState(state);
2784
- return state.cohorts.cohortManager.entities[currentCohortId]?.filters;
2785
- };
2786
- const selectCurrentCohortId = (state)=>{
2787
- return state.cohorts.cohortManager.currentCohortId;
2788
- };
2789
- const selectCurrentCohort = (state)=>cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
2790
- const selectCurrentCohortName = (state)=>cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state)).name;
2791
- /**
2792
- * Select a filter by its name from the current cohort. If the filter is not found
2793
- * returns undefined.
2794
- * @param state - Core
2795
- * @param index which cohort index to select from
2796
- * @param name name of the filter to select
2797
- */ const selectIndexedFilterByName = (state, index, name)=>{
2798
- return cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state)).filters[index]?.root[name];
2914
+ return data;
2799
2915
  };
2800
- /**
2801
- * Returns all the cohorts in the state
2802
- * @param state - the CoreState
2803
- *
2804
- * @category Cohort
2805
- * @category Selectors
2806
- */ const selectAvailableCohorts = (state)=>cohortSelectors.selectAll(state);
2807
- /**
2808
- * Returns if the current cohort is modified
2809
- * @param state - the CoreState
2810
- * @category Cohort
2811
- * @category Selectors
2812
- * @hidden
2813
- */ const selectCurrentCohortModified = (state)=>{
2814
- const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
2815
- return cohort?.modified;
2916
+
2917
+ const customQueryStrForField = (field, query, depth = 0)=>{
2918
+ const indent = ' '.repeat(depth);
2919
+ const splittedFieldArray = field.split('.');
2920
+ const splittedField = splittedFieldArray.shift();
2921
+ if (splittedFieldArray.length === 0) {
2922
+ return `${indent}${splittedField} ${query}`;
2923
+ }
2924
+ return `${indent}${splittedField} {
2925
+ ${customQueryStrForField(splittedFieldArray.join('.'), query, depth + 1)}
2926
+ ${indent}}`;
2816
2927
  };
2817
- /**
2818
- * Returns if the current cohort has been saved
2819
- * @param state - the CoreState
2820
- * @category Cohort
2821
- * @category Selectors
2822
- * @hidden
2823
- */ const selectCurrentCohortSaved = (state)=>{
2824
- const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
2825
- return cohort?.saved;
2928
+ // TODO: refactor the function below using customQueryStrForEachField and a wrapper function that passes the query
2929
+ const histogramQueryStrForEachField = (field)=>{
2930
+ const splittedFieldArray = field.split('.');
2931
+ const splittedField = splittedFieldArray.shift();
2932
+ if (splittedFieldArray.length === 0) {
2933
+ return `
2934
+ ${splittedField} {
2935
+ histogram {
2936
+ key
2937
+ count
2938
+ }
2939
+ }`;
2940
+ }
2941
+ return `
2942
+ ${splittedField} {
2943
+ ${histogramQueryStrForEachField(splittedFieldArray.join('.'))}
2944
+ }`;
2826
2945
  };
2827
- /**
2828
- * Select a filter by its name from the current cohort. If the filter is not found
2829
- * returns undefined.
2830
- * @param state - Core
2831
- * @param name name of the filter to select
2832
- */ const selectAvailableCohortByName = (state, name)=>cohortSelectors.selectAll(state).find((cohort)=>cohort.name === name);
2833
- /**
2834
- * Select a filter from the index.
2835
- * returns undefined.
2836
- * @param state - Core
2837
- * @param index which cohort index to select from
2838
- */ const selectIndexFilters = (state, index)=>{
2839
- const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
2840
- if (!cohort) {
2841
- console.error('No Cohort Defined');
2946
+ const statsQueryStrForEachField = (field)=>{
2947
+ const splittedFieldArray = field.split('.');
2948
+ const splittedField = splittedFieldArray.shift();
2949
+ if (splittedFieldArray.length === 0) {
2950
+ return `
2951
+ ${splittedField} {
2952
+ histogram {
2953
+ count
2954
+ min
2955
+ max
2956
+ avg
2957
+ sum
2958
+ }
2959
+ }`;
2842
2960
  }
2843
- return cohort?.filters?.[index] ?? EmptyFilterSet;
2961
+ return `
2962
+ ${splittedField} {
2963
+ ${statsQueryStrForEachField(splittedFieldArray.join('.'))}
2964
+ }`;
2844
2965
  };
2845
-
2846
- class ToGqlAllNested {
2847
- constructor(){
2848
- this.handleEquals = (op)=>{
2849
- if (op.field.includes('.')) {
2850
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2851
- return buildNestedGQLFilter(op.field, {
2852
- '=': {
2853
- [leafField]: op.operand
2854
- }
2855
- });
2856
- }
2857
- return {
2858
- '=': {
2859
- [op.field]: op.operand
2860
- }
2861
- };
2862
- };
2863
- this.handleNotEquals = (op)=>{
2864
- if (op.field.includes('.')) {
2865
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2866
- return buildNestedGQLFilter(op.field, {
2867
- '!=': {
2868
- [leafField]: op.operand
2869
- }
2870
- });
2871
- }
2872
- return {
2873
- '!=': {
2874
- [op.field]: op.operand
2875
- }
2876
- };
2877
- };
2878
- this.handleLessThan = (op)=>{
2879
- if (op.field.includes('.')) {
2880
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2881
- return buildNestedGQLFilter(op.field, {
2882
- '<': {
2883
- [leafField]: op.operand
2884
- }
2885
- });
2886
- }
2887
- return {
2888
- '<': {
2889
- [op.field]: op.operand
2890
- }
2891
- };
2892
- };
2893
- this.handleLessThanOrEquals = (op)=>{
2894
- if (op.field.includes('.')) {
2895
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2896
- return buildNestedGQLFilter(op.field, {
2897
- '<=': {
2898
- [leafField]: op.operand
2899
- }
2900
- });
2901
- }
2902
- return {
2903
- '<=': {
2904
- [op.field]: op.operand
2905
- }
2906
- };
2907
- };
2908
- this.handleGreaterThan = (op)=>{
2909
- if (op.field.includes('.')) {
2910
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2911
- return buildNestedGQLFilter(op.field, {
2912
- '>': {
2913
- [leafField]: op.operand
2914
- }
2915
- });
2916
- }
2917
- return {
2918
- '>': {
2919
- [op.field]: op.operand
2920
- }
2921
- };
2922
- };
2923
- this.handleGreaterThanOrEquals = (op)=>{
2924
- if (op.field.includes('.')) {
2925
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2926
- return buildNestedGQLFilter(op.field, {
2927
- '>=': {
2928
- [leafField]: op.operand
2929
- }
2930
- });
2931
- }
2932
- return {
2933
- '>=': {
2934
- [op.field]: op.operand
2935
- }
2936
- };
2937
- };
2938
- this.handleIncludes = (op)=>{
2939
- if (op.field.includes('.')) {
2940
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2941
- return buildNestedGQLFilter(op.field, {
2942
- in: {
2943
- [leafField]: op.operands
2944
- }
2945
- });
2946
- }
2947
- return {
2948
- in: {
2949
- [op.field]: op.operands
2950
- }
2951
- };
2952
- };
2953
- this.handleExcludes = (op)=>{
2954
- if (op.field.includes('.')) {
2955
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2956
- return buildNestedGQLFilter(op.field, {
2957
- exclude: {
2958
- [leafField]: op.operands
2959
- }
2960
- });
2961
- }
2962
- return {
2963
- exclude: {
2964
- [op.field]: op.operands
2965
- }
2966
- };
2967
- };
2968
- this.handleExcludeIfAny = (op)=>{
2969
- if (op.field.includes('.')) {
2970
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2971
- return buildNestedGQLFilter(op.field, {
2972
- excludeifany: {
2973
- [leafField]: op.operands
2974
- }
2975
- });
2976
- }
2977
- return {
2978
- excludeifany: {
2979
- [op.field]: op.operands
2980
- }
2981
- };
2982
- };
2983
- this.handleIntersection = (op)=>({
2984
- and: op.operands.map((x)=>convertFilterToGqlFilter(x))
2985
- });
2986
- this.handleUnion = (op)=>({
2987
- or: op.operands.map((x)=>convertFilterToGqlFilter(x))
2988
- });
2989
- this.handleMissing = (op)=>{
2990
- if (op.field.includes('.')) {
2991
- const leafField = op.field.split('.').at(-1) ?? 'unset';
2992
- return buildNestedGQLFilter(op.field, {
2993
- is: {
2994
- [leafField]: 'MISSING'
2995
- }
2996
- });
2966
+ const nestedHistogramQueryStrForEachField = (mainField, numericAggAsText)=>`
2967
+ ${mainField} {
2968
+ ${numericAggAsText ? 'asTextHistogram' : 'histogram'} {
2969
+ key
2970
+ count
2971
+ missingFields {
2972
+ field
2973
+ count
2974
+ }
2975
+ termsFields {
2976
+ field
2977
+ count
2978
+ terms {
2979
+ key
2980
+ count
2981
+ }
2982
+ }
2983
+ }
2984
+ }`;
2985
+ const rawDataQueryStrForEachField$1 = (field)=>{
2986
+ const splitFieldArray = field.split('.');
2987
+ const splitField = splitFieldArray.shift();
2988
+ if (splitFieldArray.length === 0) {
2989
+ return `
2990
+ ${splitField}
2991
+ `;
2992
+ }
2993
+ return `
2994
+ ${splitField} {
2995
+ ${rawDataQueryStrForEachField$1(splitFieldArray.join('.'))}
2996
+ }`;
2997
+ };
2998
+
2999
+ const convertNumericFromToArrayToFilters = (field, range, isNested = true)=>{
3000
+ const { from, to } = range;
3001
+ return {
3002
+ operator: 'and',
3003
+ operands: [
3004
+ isNested ? buildNestedFilterForOperation(field, {
3005
+ operator: '>=',
3006
+ field,
3007
+ operand: from
3008
+ }) : {
3009
+ operator: '>=',
3010
+ field,
3011
+ operand: from
3012
+ },
3013
+ isNested ? buildNestedFilterForOperation(field, {
3014
+ operator: '<',
3015
+ field,
3016
+ operand: to
3017
+ }) : {
3018
+ operator: '<',
3019
+ field,
3020
+ operand: to
2997
3021
  }
2998
- return {
2999
- is: {
3000
- [op.field]: 'MISSING'
3001
- }
3002
- };
3003
- };
3004
- this.handleExists = (op)=>{
3005
- if (op.field.includes('.')) {
3006
- const leafField = op.field.split('.').at(-1) ?? 'unset';
3007
- return buildNestedGQLFilter(op.field, {
3008
- not: {
3009
- [leafField]: op?.operand ?? null
3010
- }
3011
- });
3022
+ ]
3023
+ };
3024
+ };
3025
+ const rawDataQueryStrForEachField = (field, asTextHistogram = false)=>{
3026
+ const splitFieldArray = field.split('.');
3027
+ const splitField = splitFieldArray.shift();
3028
+ let middleQuery = '';
3029
+ if (splitFieldArray.length === 0) {
3030
+ middleQuery = `${splitField} { ${asTextHistogram ? 'histogram: asTextHistogram' : 'histogram'} { count } }`;
3031
+ } else {
3032
+ middleQuery = `${splitField} { ${rawDataQueryStrForEachField(splitFieldArray.join('.'), asTextHistogram)} }`;
3033
+ }
3034
+ return middleQuery;
3035
+ };
3036
+ const buildAliasedNestedCountsQuery = ({ type, field, rangeName, asTextHistogram = false })=>{
3037
+ const dataParams = [
3038
+ `filter: $${rangeName}`
3039
+ ];
3040
+ const dataTypeLine = `${rangeName} : ${type} (accessibility: $accessibility ${dataParams}) {`;
3041
+ const processedFields = rawDataQueryStrForEachField(field, asTextHistogram);
3042
+ return `${dataTypeLine} ${processedFields} }`;
3043
+ };
3044
+ const buildRangeFilters = (field, ranges, filters, rangeBaseName, isNested = true)=>{
3045
+ return Object.entries(ranges).reduce((acc, [, rangeValue], idx)=>{
3046
+ acc[`${rangeBaseName}_${idx}`] = {
3047
+ mode: filters.mode,
3048
+ root: {
3049
+ ...filters.root,
3050
+ [field]: convertNumericFromToArrayToFilters(field, rangeValue, isNested)
3012
3051
  }
3013
- return {
3014
- not: {
3015
- [op.field]: op?.operand ?? null
3016
- }
3017
- };
3018
- };
3019
- this.handleNestedFilter = (op)=>{
3020
- const child = convertFilterToGqlFilter(op.operand);
3021
- return {
3022
- nested: {
3023
- path: op.path,
3024
- ...child
3025
- }
3026
- };
3027
3052
  };
3028
- }
3029
- }
3030
- const convertFilterToNestedGqlFilter = (filter)=>{
3031
- const handler = new ToGqlAllNested();
3032
- return handleOperation(handler, filter);
3053
+ return acc;
3054
+ }, {});
3033
3055
  };
3034
- const convertFilterSetToNestedGqlFilter = (fs, toplevelOp = 'and')=>{
3035
- const fsKeys = Object.keys(fs.root);
3036
- // if no keys return undefined
3037
- if (fsKeys.length === 0) return {
3038
- and: []
3039
- };
3040
- return toplevelOp === 'and' ? {
3041
- and: fsKeys.map((key)=>convertFilterToNestedGqlFilter(fs.root[key]))
3042
- } : {
3043
- or: fsKeys.map((key)=>convertFilterToNestedGqlFilter(fs.root[key]))
3056
+ const buildRangeQuery = (field, ranges, filters, rangeBaseName = 'range', index = 'cases', indexPrefix = '', isNested = true, asTextHistogram = false)=>{
3057
+ const rangeFilters = buildRangeFilters(field, ranges, filters, rangeBaseName, isNested);
3058
+ let query = `query rangeQuery ($accessibility: Accessibility, ${Object.keys(rangeFilters).map((rangeKey)=>`$${rangeKey}: JSON`).join(',')} ) { ${indexPrefix}_aggregation {`;
3059
+ Object.keys(rangeFilters).forEach((rangeKey)=>{
3060
+ const rangeQuery = buildAliasedNestedCountsQuery({
3061
+ type: index,
3062
+ field,
3063
+ rangeName: rangeKey,
3064
+ asTextHistogram
3065
+ });
3066
+ query += rangeQuery + ' \n';
3067
+ });
3068
+ query += `}}`;
3069
+ return {
3070
+ query: query,
3071
+ filters: rangeFilters
3044
3072
  };
3045
3073
  };
3046
3074
 
3075
+ const GUPPY_MAX_ITEMS = 10000;
3047
3076
  const statusEndpoint = '/_status';
3048
3077
  const fetchJson = async (url)=>{
3049
3078
  const res = await fetch(url, {
@@ -3395,6 +3424,34 @@ const explorerTags = guppyApi.enhanceEndpoints({
3395
3424
  };
3396
3425
  }
3397
3426
  }),
3427
+ getObjectIds: builder.query({
3428
+ query: ({ filters, field, index, indexPrefix = '', accessibility = Accessibility.ALL, limit = GUPPY_MAX_ITEMS })=>{
3429
+ const gqlFilter = convertFilterSetToGqlFilter(filters);
3430
+ const query = `query getObjectIds ($filter: JSON) {
3431
+ ${indexPrefix}${index} (filter: $filter, accessibility: ${accessibility}, first: ${limit}) {
3432
+ ${rawDataQueryStrForEachField$1(field)}
3433
+ }
3434
+ }`;
3435
+ return {
3436
+ query,
3437
+ variables: {
3438
+ filter: gqlFilter,
3439
+ accessibility
3440
+ }
3441
+ };
3442
+ },
3443
+ transformResponse: (response, _, args)=>{
3444
+ const valueData = jsonpathPlus.JSONPath({
3445
+ json: response?.data ?? [],
3446
+ path: `$..${args.field}`,
3447
+ resultType: 'value'
3448
+ });
3449
+ return {
3450
+ ids: valueData,
3451
+ index: args.index
3452
+ };
3453
+ }
3454
+ }),
3398
3455
  generalGQL: builder.query({
3399
3456
  query: ({ query, variables })=>{
3400
3457
  return {
@@ -3460,7 +3517,7 @@ const buildGetStatsAggregationQuery = (type, fields, filters, accessibility = Ac
3460
3517
  };
3461
3518
  return queryBody;
3462
3519
  };
3463
- const { useGetRawDataAndTotalCountsQuery, useGetAccessibleDataQuery, useGetAllFieldsForTypeQuery, useGetAggsQuery, useLazyGetAggsQuery, useGetStatsAggregationsQuery, useLazyGetStatsAggregationsQuery, useGetSubAggsQuery, useGetCountsQuery, useLazyGetCountsQuery, useGetFieldCountSummaryQuery, useGetFieldsForIndexQuery, useGetSharedFieldsForIndexQuery, useGeneralGQLQuery, useLazyGeneralGQLQuery, useCustomRangeQuery, useLazyCustomRangeQuery } = explorerApi;
3520
+ const { useGetRawDataAndTotalCountsQuery, useGetAccessibleDataQuery, useGetAllFieldsForTypeQuery, useGetAggsQuery, useLazyGetAggsQuery, useGetStatsAggregationsQuery, useLazyGetStatsAggregationsQuery, useGetSubAggsQuery, useGetCountsQuery, useLazyGetCountsQuery, useGetFieldCountSummaryQuery, useGetFieldsForIndexQuery, useGetSharedFieldsForIndexQuery, useGeneralGQLQuery, useLazyGeneralGQLQuery, useCustomRangeQuery, useLazyCustomRangeQuery, useGetObjectIdsQuery, useLazyGetObjectIdsQuery } = explorerApi;
3464
3521
 
3465
3522
  /**
3466
3523
  * Defines coreListeners for adding middleware.
@@ -4030,6 +4087,81 @@ class CohortStorage {
4030
4087
  }
4031
4088
  }
4032
4089
 
4090
+ const { selectAll: selectAllCohorts, selectTotal: selectTotalCohorts, selectById: selectCohortById, selectIds: selectCohortIds } = cohortsAdapter.getSelectors((state)=>state.cohorts.cohortManager);
4091
+ /**
4092
+ * Internally used selector for the exported selectora
4093
+ * @param state
4094
+ */ const getCurrentCohortFromCoreState = (state)=>{
4095
+ return state.cohorts.cohortManager.currentCohortId;
4096
+ };
4097
+ const selectCohortFilters = (state)=>{
4098
+ const currentCohortId = getCurrentCohortFromCoreState(state);
4099
+ return state.cohorts.cohortManager.entities[currentCohortId]?.filters;
4100
+ };
4101
+ const selectCurrentCohortFilters = (state)=>{
4102
+ const currentCohortId = getCurrentCohortFromCoreState(state);
4103
+ return state.cohorts.cohortManager.entities[currentCohortId]?.filters;
4104
+ };
4105
+ const selectCurrentCohortId = (state)=>{
4106
+ return state.cohorts.cohortManager.currentCohortId;
4107
+ };
4108
+ const selectCurrentCohort = (state)=>cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
4109
+ const selectCurrentCohortName = (state)=>cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state)).name;
4110
+ /**
4111
+ * Select a filter by its name from the current cohort. If the filter is not found
4112
+ * returns undefined.
4113
+ * @param state - Core
4114
+ * @param index which cohort index to select from
4115
+ * @param name name of the filter to select
4116
+ */ const selectIndexedFilterByName = (state, index, name)=>{
4117
+ return cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state)).filters[index]?.root[name];
4118
+ };
4119
+ /**
4120
+ * Returns all the cohorts in the state
4121
+ * @param state - the CoreState
4122
+ *
4123
+ * @category Cohort
4124
+ * @category Selectors
4125
+ */ const selectAvailableCohorts = (state)=>cohortSelectors.selectAll(state);
4126
+ /**
4127
+ * Returns if the current cohort is modified
4128
+ * @param state - the CoreState
4129
+ * @category Cohort
4130
+ * @category Selectors
4131
+ * @hidden
4132
+ */ const selectCurrentCohortModified = (state)=>{
4133
+ const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
4134
+ return cohort?.modified;
4135
+ };
4136
+ /**
4137
+ * Returns if the current cohort has been saved
4138
+ * @param state - the CoreState
4139
+ * @category Cohort
4140
+ * @category Selectors
4141
+ * @hidden
4142
+ */ const selectCurrentCohortSaved = (state)=>{
4143
+ const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
4144
+ return cohort?.saved;
4145
+ };
4146
+ /**
4147
+ * Select a filter by its name from the current cohort. If the filter is not found
4148
+ * returns undefined.
4149
+ * @param state - Core
4150
+ * @param name name of the filter to select
4151
+ */ const selectAvailableCohortByName = (state, name)=>cohortSelectors.selectAll(state).find((cohort)=>cohort.name === name);
4152
+ /**
4153
+ * Select a filter from the index.
4154
+ * returns undefined.
4155
+ * @param state - Core
4156
+ * @param index which cohort index to select from
4157
+ */ const selectIndexFilters = (state, index)=>{
4158
+ const cohort = cohortSelectors.selectById(state, getCurrentCohortFromCoreState(state));
4159
+ if (!cohort) {
4160
+ console.error('No Cohort Defined');
4161
+ }
4162
+ return cohort?.filters?.[index] ?? EmptyFilterSet;
4163
+ };
4164
+
4033
4165
  const isFileItem = (item)=>{
4034
4166
  return item && 'guid' in item;
4035
4167
  };
@@ -6298,6 +6430,87 @@ class ConfigRegistry {
6298
6430
  }
6299
6431
  const configRegistry = new ConfigRegistry();
6300
6432
 
6433
+ const DAYS_IN_DECADE = 3652; // Note: an approximation
6434
+ const cohortFacetSlice = graphQLAPI.injectEndpoints({
6435
+ endpoints: (builder)=>({
6436
+ cohortFacets: builder.query({
6437
+ query: ({ index, facetFields, continuousFacets, primaryCohort, comparisonCohort })=>({
6438
+ url: `${GEN3_ANALYSIS_API}/compare/facets`,
6439
+ method: 'POST',
6440
+ body: {
6441
+ doc_type: index,
6442
+ cohort1: primaryCohort,
6443
+ cohort2: comparisonCohort,
6444
+ facets: facetFields,
6445
+ interval: continuousFacets.reduce((acc, x)=>{
6446
+ acc[x] = DAYS_IN_DECADE;
6447
+ return acc;
6448
+ }, {})
6449
+ }
6450
+ }),
6451
+ transformResponse: (response)=>{
6452
+ const facets1 = response?.cohort1?.facets;
6453
+ const facets2 = response?.cohort2?.facets;
6454
+ return {
6455
+ aggregations: [
6456
+ facets1,
6457
+ facets2
6458
+ ]
6459
+ };
6460
+ }
6461
+ })
6462
+ })
6463
+ });
6464
+ const { useCohortFacetsQuery } = cohortFacetSlice;
6465
+
6466
+ const vennDiagramApiSlice = graphQLAPI.injectEndpoints({
6467
+ endpoints: (builder)=>({
6468
+ vennDiagram: builder.query({
6469
+ query: (queryParameters)=>{
6470
+ return {
6471
+ url: `${GEN3_ANALYSIS_API}/compare/intersection`,
6472
+ method: 'POST',
6473
+ body: JSON.stringify({
6474
+ cohort1: queryParameters.set1Filters,
6475
+ cohort2: queryParameters.set2Filters,
6476
+ doc_type: queryParameters.index
6477
+ })
6478
+ };
6479
+ },
6480
+ transformResponse: (response)=>({
6481
+ set1: response?.cohort1,
6482
+ set2: response?.cohort2,
6483
+ intersection: response?.intersection
6484
+ })
6485
+ })
6486
+ })
6487
+ });
6488
+ const { useVennDiagramQuery } = vennDiagramApiSlice;
6489
+
6490
+ const graphQLQuery = `
6491
+ query pValue($data: [[Int]]!) {
6492
+ analysis {
6493
+ pvalue(data: $data)
6494
+ }
6495
+ }
6496
+ `;
6497
+ const pValueSlice = graphQLAPI.injectEndpoints({
6498
+ endpoints: (builder)=>({
6499
+ pValue: builder.query({
6500
+ query: (data)=>({
6501
+ url: `${GEN3_ANALYSIS_API}/pvalue`,
6502
+ method: 'POST',
6503
+ body: {
6504
+ query: graphQLQuery,
6505
+ variables: data
6506
+ }
6507
+ }),
6508
+ transformResponse: (response)=>response?.data?.analysis.pvalue
6509
+ })
6510
+ })
6511
+ });
6512
+ const { usePValueQuery } = pValueSlice;
6513
+
6301
6514
  exports.Accessibility = Accessibility;
6302
6515
  exports.CART_LIMIT = CART_LIMIT;
6303
6516
  exports.CohortStorage = CohortStorage;
@@ -6334,17 +6547,20 @@ exports.Modals = Modals;
6334
6547
  exports.PodConditionType = PodConditionType;
6335
6548
  exports.PodStatus = PodStatus;
6336
6549
  exports.RequestedWorkspaceStatus = RequestedWorkspaceStatus;
6550
+ exports.ToGqlAllNested = ToGqlAllNested;
6337
6551
  exports.ToGqlHandler = ToGqlHandler;
6338
6552
  exports.ValueExtractorHandler = ValueExtractorHandler;
6339
6553
  exports.WorkspaceStatus = WorkspaceStatus;
6340
6554
  exports.addItemsToCart = addItemsToCart;
6341
6555
  exports.ageDisplay = ageDisplay;
6342
6556
  exports.appendFilterToOperation = appendFilterToOperation;
6557
+ exports.buildCohortGqlOperator = buildCohortGqlOperator;
6343
6558
  exports.buildGetAggregationQuery = buildGetAggregationQuery;
6344
6559
  exports.buildGetStatsAggregationQuery = buildGetStatsAggregationQuery;
6345
6560
  exports.buildListItemsGroupedByDataset = buildListItemsGroupedByDataset;
6346
6561
  exports.buildNestedFilterForOperation = buildNestedFilterForOperation;
6347
6562
  exports.buildNestedGQLFilter = buildNestedGQLFilter;
6563
+ exports.buildNestedWithParentPathGQLFilter = buildNestedWithParentPathGQLFilter;
6348
6564
  exports.buildRangeQuery = buildRangeQuery;
6349
6565
  exports.calculatePercentageAsNumber = calculatePercentageAsNumber;
6350
6566
  exports.calculatePercentageAsString = calculatePercentageAsString;
@@ -6357,7 +6573,10 @@ exports.cohortReducer = cohortReducer;
6357
6573
  exports.configRegistry = configRegistry;
6358
6574
  exports.conversion = conversion;
6359
6575
  exports.convertFilterSetToGqlFilter = convertFilterSetToGqlFilter;
6576
+ exports.convertFilterSetToNestedGqlFilter = convertFilterSetToNestedGqlFilter;
6577
+ exports.convertFilterSetToOperation = convertFilterSetToOperation;
6360
6578
  exports.convertFilterToGqlFilter = convertFilterToGqlFilter;
6579
+ exports.convertFilterToNestedGqlFilter = convertFilterToNestedGqlFilter;
6361
6580
  exports.convertGqlFilterToFilter = convertGqlFilterToFilter;
6362
6581
  exports.convertToHistogramDataAsStringKey = convertToHistogramDataAsStringKey;
6363
6582
  exports.convertToQueryString = convertToQueryString;
@@ -6376,6 +6595,7 @@ exports.drsHostnamesReducer = drsHostnamesReducer;
6376
6595
  exports.duplicateCohort = duplicateCohort;
6377
6596
  exports.explorerApi = explorerApi;
6378
6597
  exports.explorerTags = explorerTags;
6598
+ exports.extractContents = extractContents;
6379
6599
  exports.extractEnumFilterValue = extractEnumFilterValue;
6380
6600
  exports.extractFieldNameFromFullFieldName = extractFieldNameFromFullFieldName;
6381
6601
  exports.extractFileDatasetsInRecords = extractFileDatasetsInRecords;
@@ -6390,7 +6610,7 @@ exports.fetchFencePresignedURL = fetchFencePresignedURL;
6390
6610
  exports.fetchJSONDataFromURL = fetchJSONDataFromURL;
6391
6611
  exports.fetchJson = fetchJson;
6392
6612
  exports.fetchUserState = fetchUserState;
6393
- exports.fieldNameToTitle = fieldNameToTitle;
6613
+ exports.fieldNameToLabel = fieldNameToLabel;
6394
6614
  exports.filterSetToOperation = filterSetToOperation;
6395
6615
  exports.gen3Api = gen3Api;
6396
6616
  exports.generateUniqueName = generateUniqueName;
@@ -6463,6 +6683,7 @@ exports.isTimeGreaterThan = isTimeGreaterThan;
6463
6683
  exports.isUnion = isUnion;
6464
6684
  exports.isWorkspaceActive = isWorkspaceActive;
6465
6685
  exports.isWorkspaceRunningOrStopping = isWorkspaceRunningOrStopping;
6686
+ exports.joinFilters = joinFilters;
6466
6687
  exports.jsonToFormat = jsonToFormat;
6467
6688
  exports.listifyMethodsFromMapping = listifyMethodsFromMapping;
6468
6689
  exports.logoutFence = logoutFence;
@@ -6547,7 +6768,7 @@ exports.stringifyJSONParam = stringifyJSONParam;
6547
6768
  exports.submissionApi = submissionApi;
6548
6769
  exports.toggleCohortBuilderAllFilters = toggleCohortBuilderAllFilters;
6549
6770
  exports.toggleCohortBuilderCategoryFilter = toggleCohortBuilderCategoryFilter;
6550
- exports.trimFirstFieldNameToTitle = trimFirstFieldNameToTitle;
6771
+ exports.trimFirstfieldNameToLabel = trimFirstfieldNameToLabel;
6551
6772
  exports.updateCohortFilter = updateCohortFilter;
6552
6773
  exports.updateCohortName = updateCohortName;
6553
6774
  exports.useAddCohortManifestMutation = useAddCohortManifestMutation;
@@ -6556,6 +6777,7 @@ exports.useAddMetadataManifestMutation = useAddMetadataManifestMutation;
6556
6777
  exports.useAddNewCredentialMutation = useAddNewCredentialMutation;
6557
6778
  exports.useAskQuestionMutation = useAskQuestionMutation;
6558
6779
  exports.useAuthorizeFromCredentialsMutation = useAuthorizeFromCredentialsMutation;
6780
+ exports.useCohortFacetsQuery = useCohortFacetsQuery;
6559
6781
  exports.useCoreDispatch = useCoreDispatch;
6560
6782
  exports.useCoreSelector = useCoreSelector;
6561
6783
  exports.useCreateAuthzResourceMutation = useCreateAuthzResourceMutation;
@@ -6598,6 +6820,7 @@ exports.useGetManifestServiceStatusQuery = useGetManifestServiceStatusQuery;
6598
6820
  exports.useGetMetadataByIdQuery = useGetMetadataByIdQuery;
6599
6821
  exports.useGetMetadataFromManifestQuery = useGetMetadataFromManifestQuery;
6600
6822
  exports.useGetMetadataManifestQuery = useGetMetadataManifestQuery;
6823
+ exports.useGetObjectIdsQuery = useGetObjectIdsQuery;
6601
6824
  exports.useGetPresignedUrlQuery = useGetPresignedUrlQuery;
6602
6825
  exports.useGetProjectsDetailsQuery = useGetProjectsDetailsQuery;
6603
6826
  exports.useGetProjectsQuery = useGetProjectsQuery;
@@ -6633,6 +6856,7 @@ exports.useLazyGetCrosswalkDataQuery = useLazyGetCrosswalkDataQuery;
6633
6856
  exports.useLazyGetDownloadQuery = useLazyGetDownloadQuery;
6634
6857
  exports.useLazyGetExternalLoginsQuery = useLazyGetExternalLoginsQuery;
6635
6858
  exports.useLazyGetManifestServiceStatusQuery = useLazyGetManifestServiceStatusQuery;
6859
+ exports.useLazyGetObjectIdsQuery = useLazyGetObjectIdsQuery;
6636
6860
  exports.useLazyGetPresignedUrlQuery = useLazyGetPresignedUrlQuery;
6637
6861
  exports.useLazyGetProjectsQuery = useLazyGetProjectsQuery;
6638
6862
  exports.useLazyGetSowerJobListQuery = useLazyGetSowerJobListQuery;
@@ -6640,6 +6864,7 @@ exports.useLazyGetStatsAggregationsQuery = useLazyGetStatsAggregationsQuery;
6640
6864
  exports.useLazyGetSubmissionGraphQLQuery = useLazyGetSubmissionGraphQLQuery;
6641
6865
  exports.useLazyIsExternalConnectedQuery = useLazyIsExternalConnectedQuery;
6642
6866
  exports.useLazyRequestQuery = useLazyRequestQuery;
6867
+ exports.usePValueQuery = usePValueQuery;
6643
6868
  exports.usePrevious = usePrevious;
6644
6869
  exports.useRemoveCredentialMutation = useRemoveCredentialMutation;
6645
6870
  exports.useRequestByIdQuery = useRequestByIdQuery;
@@ -6650,6 +6875,7 @@ exports.useSubmitSowerJobMutation = useSubmitSowerJobMutation;
6650
6875
  exports.useTerminateWorkspaceMutation = useTerminateWorkspaceMutation;
6651
6876
  exports.useUserAuth = useUserAuth;
6652
6877
  exports.useUserRequestQuery = useUserRequestQuery;
6878
+ exports.useVennDiagramQuery = useVennDiagramQuery;
6653
6879
  exports.userHasCreateOrUpdateOnAnyProject = userHasCreateOrUpdateOnAnyProject;
6654
6880
  exports.userHasDataUpload = userHasDataUpload;
6655
6881
  exports.userHasMethodForServiceOnProject = userHasMethodForServiceOnProject;