diff --git a/components/frontend/src/AppUI.js b/components/frontend/src/AppUI.js index 9172382709..d89940ba4d 100644 --- a/components/frontend/src/AppUI.js +++ b/components/frontend/src/AppUI.js @@ -99,6 +99,7 @@ export function AppUI({ clearVisibleDetailsTabs={clearVisibleDetailsTabs} dateInterval={dateInterval} dateOrder={dateOrder} + handleSort={handleSort} hiddenColumns={hiddenColumns} hideMetricsNotRequiringAction={hideMetricsNotRequiringAction} nrDates={nrDates} @@ -109,8 +110,6 @@ export function AppUI({ setShowIssueCreationDate={setShowIssueCreationDate} setShowIssueSummary={setShowIssueSummary} setShowIssueUpdateDate={setShowIssueUpdateDate} - setSortColumn={setSortColumn} - setSortDirection={setSortDirection} setUIMode={setUIMode} showIssueCreationDate={showIssueCreationDate} showIssueSummary={showIssueSummary} diff --git a/components/frontend/src/header_footer/ViewPanel.js b/components/frontend/src/header_footer/ViewPanel.js index 147f8a7fc3..d6441a482f 100644 --- a/components/frontend/src/header_footer/ViewPanel.js +++ b/components/frontend/src/header_footer/ViewPanel.js @@ -1,6 +1,6 @@ import React from 'react'; import { Button, Grid, Header, Menu, Segment } from 'semantic-ui-react'; -import { Popup } from '../semantic_ui_react_wrappers'; +import { Icon, Popup } from '../semantic_ui_react_wrappers'; import { capitalize, pluralize } from "../utils"; import './ViewPanel.css'; @@ -11,6 +11,7 @@ export function ViewPanel({ clearVisibleDetailsTabs, dateInterval, dateOrder, + handleSort, hiddenColumns, hideMetricsNotRequiringAction, nrDates, @@ -21,8 +22,6 @@ export function ViewPanel({ setShowIssueCreationDate, setShowIssueSummary, setShowIssueUpdateDate, - setSortColumn, - setSortDirection, setUIMode, showIssueCreationDate, showIssueSummary, @@ -35,7 +34,7 @@ export function ViewPanel({ }) { const multipleDateColumns = nrDates > 1 const oneDateColumn = nrDates === 1 - const sortOrderNotChangeable = sortColumn === null || (multipleDateColumns && ["status", "measurement", "target"].includes(sortColumn)) + hiddenColumns = hiddenColumns ?? []; return (
Sort column
- - - - - - - - - - - - -
Sort direction
- - - + + + + + + + + +
@@ -208,12 +199,18 @@ function VisibleColumnMenuItem({ column, disabled, hiddenColumns, toggleHiddenCo ) } -function SortColumnMenuItem({ column, disabled, sortColumn, setSortColumn }) { - const newColumn = sortColumn === column ? null : column +function SortColumnMenuItem({ column, disabled, sortColumn, sortDirection, handleSort }) { + const active = disabled ? false : sortColumn === column; + let sortIndicator = null; + if (sortColumn === column && sortDirection) { + // We use a triangle because the sort down and up icons are not at the same height + const iconDirection = sortDirection === "ascending" ? "up" : "down" + sortIndicator = + } return ( -
{ event.preventDefault(); setSortColumn(newColumn) }} tabIndex={0}> - setSortColumn(newColumn)}> - {capitalize(column === "name" ? "metric" : column)} +
{ event.preventDefault(); if (!disabled) { handleSort(column) } }} tabIndex={0}> + handleSort(column)}> + {capitalize(column === "name" ? "metric" : column)} {sortIndicator}
) diff --git a/components/frontend/src/header_footer/ViewPanel.test.js b/components/frontend/src/header_footer/ViewPanel.test.js index 7c0bfc5777..b88f36c85a 100644 --- a/components/frontend/src/header_footer/ViewPanel.test.js +++ b/components/frontend/src/header_footer/ViewPanel.test.js @@ -24,6 +24,7 @@ function eventHandlers() { return { clearHiddenColumns: jest.fn(), clearVisibleDetailsTabs: jest.fn(), + handleSort: jest.fn(), setDateInterval: jest.fn(), setDateOrder: jest.fn(), setHideMetricsNotRequiringAction: jest.fn(), @@ -31,8 +32,6 @@ function eventHandlers() { setShowIssueCreationDate: jest.fn(), setShowIssueSummary: jest.fn(), setShowIssueUpdateDate: jest.fn(), - setSortColumn: jest.fn(), - setSortDirection: jest.fn(), setUIMode: jest.fn() } } @@ -61,6 +60,7 @@ it('resets the settings', async () => { }); expect(props.clearVisibleDetailsTabs).toHaveBeenCalled() expect(props.clearHiddenColumns).toHaveBeenCalled() + expect(props.handleSort).toHaveBeenCalled() expect(props.setDateInterval).toHaveBeenCalled() expect(props.setDateOrder).toHaveBeenCalled() expect(props.setNrDates).toHaveBeenCalled() @@ -68,8 +68,6 @@ it('resets the settings', async () => { expect(props.setShowIssueCreationDate).toHaveBeenCalledWith(false) expect(props.setShowIssueSummary).toHaveBeenCalledWith(false) expect(props.setShowIssueUpdateDate).toHaveBeenCalledWith(false) - expect(props.setSortColumn).toHaveBeenCalledWith(null) - expect(props.setSortDirection).toHaveBeenCalledWith("ascending") expect(props.setUIMode).toHaveBeenCalledWith(null) }) @@ -97,6 +95,7 @@ it('does not reset the settings when all have the default value', async () => { }); expect(props.clearVisibleDetailsTabs).not.toHaveBeenCalled() expect(props.clearHiddenColumns).not.toHaveBeenCalled() + expect(props.handleSort).not.toHaveBeenCalled() expect(props.setDateInterval).not.toHaveBeenCalled() expect(props.setDateOrder).not.toHaveBeenCalled() expect(props.setNrDates).not.toHaveBeenCalled() @@ -104,8 +103,6 @@ it('does not reset the settings when all have the default value', async () => { expect(props.setShowIssueCreationDate).not.toHaveBeenCalled() expect(props.setShowIssueSummary).not.toHaveBeenCalled() expect(props.setShowIssueUpdateDate).not.toHaveBeenCalled() - expect(props.setSortColumn).not.toHaveBeenCalled() - expect(props.setSortDirection).not.toHaveBeenCalled() expect(props.setUIMode).not.toHaveBeenCalled() }) @@ -191,39 +188,39 @@ it("shows a column", async () => { }) it("sorts a column", async () => { - const setSortColumn = jest.fn(); + const handleSort = jest.fn(); await act(async () => { - render() + render() fireEvent.click(screen.getAllByText(/Comment/)[1]) }); - expect(setSortColumn).toHaveBeenCalledWith("comment") + expect(handleSort).toHaveBeenCalledWith("comment") }) -it("unsorts a column", async () => { - const setSortColumn = jest.fn(); +it("sorts a column descending", async () => { + const handleSort = jest.fn(); await act(async () => { - render() + render() fireEvent.click(screen.getAllByText(/Comment/)[1]) }); - expect(setSortColumn).toHaveBeenCalledWith(null) + expect(handleSort).toHaveBeenCalledWith("comment") }) it("sorts a column by keypress", async () => { - const setSortColumn = jest.fn(); + const handleSort = jest.fn(); await act(async () => { - render() + render() await userEvent.type(screen.getAllByText(/Comment/)[1], "{Enter}") }); - expect(setSortColumn).toHaveBeenCalledWith("comment") + expect(handleSort).toHaveBeenCalledWith("comment") }) -it("unsorts a column by keypress", async () => { - const setSortColumn = jest.fn(); +it("ignores a keypress if the menu item is disabled", async () => { + const handleSort = jest.fn(); await act(async () => { - render() + render() await userEvent.type(screen.getAllByText(/Comment/)[1], "{Enter}") }); - expect(setSortColumn).toHaveBeenCalledWith(null) + expect(handleSort).not.toHaveBeenCalledWith("comment") }) it("sets the number of dates", async () => { @@ -275,7 +272,7 @@ it("sorts the dates descending", async () => { const setDateOrder = jest.fn(); await act(async () => { render() - fireEvent.click(screen.getAllByText(/Descending/)[1]) + fireEvent.click(screen.getByText(/Descending/)) }); expect(setDateOrder).toHaveBeenCalledWith("descending") }) @@ -284,7 +281,7 @@ it("sorts the dates ascending by keypress", async () => { const setDateOrder = jest.fn(); await act(async () => { render() - await userEvent.type(screen.getAllByText(/Ascending/)[1], "{Enter}") + await userEvent.type(screen.getByText(/Ascending/), "{Enter}") }); expect(setDateOrder).toHaveBeenCalledWith("ascending") }) diff --git a/docs/src/changelog.md b/docs/src/changelog.md index 11cc596cc8..5a8ff1d3f4 100644 --- a/docs/src/changelog.md +++ b/docs/src/changelog.md @@ -8,13 +8,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) -## v3.35.0-rc.2 - 2022-04-06 +## [Unreleased] ### Fixed - When using Axe CVS as source for the accessibility violations metric, the "nested-interactive" violation type would be ignored by *Quality-time*. Fixes [#3628](https://github.com/ICTU/quality-time/issues/3628). - When using Gatling as source for the source version metric, the source version would not be found, when the version number was not present on the first line of the simulation.log. Fixes [#3661](https://github.com/ICTU/quality-time/issues/3661). +### Changed + +- In the settings panel under the "Sort column" setting, clicking the same column multiple times now alternates between ascending and descending sort order. This makes the setting consistent with how column headers behave. It also removes the need for a separate "Sort direction" setting in the settings panel. Closes [#3646](https://github.com/ICTU/quality-time/issues/3646). + ### Removed - The Axe CSV "violation type" parameter that could be used to select which violation types to count has been removed to help fix [#3628](https://github.com/ICTU/quality-time/issues/3628). The parameter was already not very practical to ignore certain violation types because it would require the user to select all violation types except the ones to be ignored. Also, if Axe adds new violation types, *Quality-time* would need to be updated to prevent it from ignoring the new violation types.