diff --git a/packages/synapse-react-client/src/components/QueryWrapperPlotNav/QueryWrapperPlotNav.tsx b/packages/synapse-react-client/src/components/QueryWrapperPlotNav/QueryWrapperPlotNav.tsx index 7682ae267c..3c22742198 100644 --- a/packages/synapse-react-client/src/components/QueryWrapperPlotNav/QueryWrapperPlotNav.tsx +++ b/packages/synapse-react-client/src/components/QueryWrapperPlotNav/QueryWrapperPlotNav.tsx @@ -69,6 +69,10 @@ type QueryWrapperPlotNavOwnProps = { > facetsToPlot?: string[] availableFacets?: FacetFilterControlsProps['availableFacets'] + /** + * Controls the sort order (ascending or descending) of facet values for a particular column. + * Note: This parameter does not currently apply to the pie/bar chart visualizations, but it probably should. + */ facetValueSortConfigs?: FacetFilterControlsProps['facetValueSortConfigs'] customPlots?: QueryWrapperSynapsePlotProps[] defaultColumn?: string diff --git a/packages/synapse-react-client/src/components/SharePageLinkButton/SharePageLinkButton.test.tsx b/packages/synapse-react-client/src/components/SharePageLinkButton/SharePageLinkButton.test.tsx index 26b11c7934..9734c3e62d 100644 --- a/packages/synapse-react-client/src/components/SharePageLinkButton/SharePageLinkButton.test.tsx +++ b/packages/synapse-react-client/src/components/SharePageLinkButton/SharePageLinkButton.test.tsx @@ -19,15 +19,14 @@ describe('SharePageLinkButton', () => { afterAll(() => server.close()) beforeEach(() => { jest.clearAllMocks() - // Replace clipboard.writeText with a mock + }) + + it('Copies short.io response to clipboard', async () => { Object.assign(navigator, { clipboard: { writeText: jest.fn().mockImplementation(() => Promise.resolve()), }, }) - }) - - it('Copies short.io response to clipboard', async () => { renderComponent({ shortIoPublicApiKey: 'abc' }) expect(screen.queryByRole('alert')).not.toBeInTheDocument() diff --git a/packages/synapse-react-client/src/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.integration.test.tsx b/packages/synapse-react-client/src/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.integration.test.tsx index 6b01b34cbe..3ce7ad7d7f 100644 --- a/packages/synapse-react-client/src/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.integration.test.tsx +++ b/packages/synapse-react-client/src/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.integration.test.tsx @@ -66,6 +66,16 @@ const entityFacetValues: FacetColumnResultValueCount[] = [ { value: mockTableEntity.id.replace('syn', ''), count: 1, isSelected: false }, ] +const integerFacetValues: FacetColumnResultValueCount[] = [ + { value: '20030', count: 2, isSelected: false }, + { value: '2010', count: 1, isSelected: true }, + { + value: SynapseConstants.VALUE_NOT_SET, + count: 1, + isSelected: false, + }, +] + const columnModel: ColumnModel = { columnType: ColumnTypeEnum.STRING, facetType: 'enumeration', @@ -80,6 +90,19 @@ const facet: FacetColumnResultValues = { concreteType: 'org.sagebionetworks.repo.model.table.FacetColumnResultValues', } +const integerColumnModel: ColumnModel = { + columnType: ColumnTypeEnum.INTEGER, + facetType: 'enumeration', + id: '86424', + name: 'Year', +} +const integerFacet: FacetColumnResultValues = { + columnName: 'Year', + facetType: 'enumeration', + facetValues: integerFacetValues, + concreteType: 'org.sagebionetworks.repo.model.table.FacetColumnResultValues', +} + function createTestProps( overrides?: Partial, ): EnumFacetFilterProps { @@ -194,6 +217,40 @@ describe('EnumFacetFilter', () => { expect(counts[2]).toHaveTextContent(`${stringFacetValues[2].count}`) }) + it('should set labels correctly for INTEGER type', async () => { + registerTableQueryResult(nextQueryRequest.query, { + ...mockQueryResponseData, + columnModels: [integerColumnModel], + }) + const { container } = await init({ facet: integerFacet }) + + const checkboxes = await screen.findAllByRole( + 'checkbox', + ) + const counts = container.querySelectorAll( + '.EnumFacetFilter__count', + ) + + expect(checkboxes).toHaveLength(4) + expect(counts).toHaveLength(3) + + expect(checkboxes[0]).toHaveAccessibleName('All') + + // Note: Facet values are resorted to numberical order! [1] should appear before [0] + expect(checkboxes[1]).toHaveAccessibleName( + `${integerFacetValues[1].value}`, + ) + expect(counts[0]).toHaveTextContent(`${integerFacetValues[1].count}`) + + expect(checkboxes[2]).toHaveAccessibleName( + `${integerFacetValues[0].value}`, + ) + expect(counts[1]).toHaveTextContent(`${integerFacetValues[0].count}`) + + expect(checkboxes[3]).toHaveAccessibleName(`Not Assigned`) + expect(counts[2]).toHaveTextContent(`${integerFacetValues[2].count}`) + }) + it('should reverse sort order if configured', async () => { const { container } = await init({ sortConfig: { diff --git a/packages/synapse-react-client/src/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.tsx b/packages/synapse-react-client/src/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.tsx index ddab8389ba..95d807b0a2 100644 --- a/packages/synapse-react-client/src/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.tsx +++ b/packages/synapse-react-client/src/components/widgets/query-filter/EnumFacetFilter/EnumFacetFilter.tsx @@ -90,6 +90,17 @@ function _EnumFacetFilter(props: EnumFacetFilterProps) { ? getCorrespondingColumnForFacet(facet, queryMetadata.columnModels) : undefined + const isNumberColumnType = useMemo(() => { + switch (columnModel?.columnType) { + case ColumnTypeEnum.DOUBLE: + case ColumnTypeEnum.DATE: + case ColumnTypeEnum.INTEGER: + return true + default: + return false + } + }, [columnModel]) + const userIds = columnModel?.columnType === ColumnTypeEnum.USERID || columnModel?.columnType === ColumnTypeEnum.USERID_LIST @@ -145,9 +156,15 @@ function _EnumFacetFilter(props: EnumFacetFilterProps) { ) const valueNotSetFacetArray = partitions[0] const restOfFacetValuesArray = partitions[1] - const sortedValues = sortBy(restOfFacetValuesArray, fv => - fv.displayText.toLowerCase(), - ) + let sortedValues: RenderedFacetValue[] + if (isNumberColumnType) { + sortedValues = sortBy(restOfFacetValuesArray, fv => new Number(fv.value)) + } else { + sortedValues = sortBy(restOfFacetValuesArray, fv => + fv.displayText.toLowerCase(), + ) + } + //PORTALS-3252: provide way to sort in descending order on the client-side const sortDescending = sortConfig && sortConfig.direction == Direction.DESC return [ diff --git a/packages/synapse-react-client/src/components/widgets/query-filter/FacetFilterControls.tsx b/packages/synapse-react-client/src/components/widgets/query-filter/FacetFilterControls.tsx index fb3b07b1f9..067f4ca601 100644 --- a/packages/synapse-react-client/src/components/widgets/query-filter/FacetFilterControls.tsx +++ b/packages/synapse-react-client/src/components/widgets/query-filter/FacetFilterControls.tsx @@ -6,7 +6,6 @@ import { isSingleNotSetValue, } from '../../../utils/functions/queryUtils' import { - Direction, FacetColumnRequest, FacetColumnResultRange, FacetColumnResultValues,