forked from quarkusio/extensions
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Allow sorting alphabetically and chronologically
- Loading branch information
1 parent
b8a3069
commit aef5849
Showing
8 changed files
with
300 additions
and
49 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
46 changes: 46 additions & 0 deletions
46
src/components/sortings/alphabetical-extension-comparator.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
const HOURS_IN_MS = 60 * 60 * 1000 | ||
|
||
function compareByTimestamp(a, b) { | ||
const timestampA = roundToTheNearestHour(a?.metadata?.maven?.timestamp) | ||
const timestampB = roundToTheNearestHour(b?.metadata?.maven?.timestamp) | ||
|
||
if (timestampA && timestampB) { | ||
const delta = timestampB - timestampA | ||
if (delta === 0) { | ||
return compareAlphabetically(a, b) | ||
} else { | ||
return delta | ||
} | ||
} else if (timestampA) { | ||
return -1 | ||
} else if (timestampB) { | ||
return 1 | ||
} | ||
} | ||
|
||
const alphabeticalExtensionComparator = (a, b) => { | ||
|
||
let comp = compareAlphabetically(a, b) | ||
if (comp === 0) { | ||
comp = compareByTimestamp(a, b) | ||
} | ||
return comp | ||
} | ||
|
||
function roundToTheNearestHour(n) { | ||
if (n) { | ||
return Math.round(n / HOURS_IN_MS) * HOURS_IN_MS | ||
} | ||
} | ||
|
||
function compareAlphabetically(a, b) { | ||
if (a.sortableName) { | ||
return a.sortableName.localeCompare(b.sortableName) | ||
} else if (b.sortableName) { | ||
return 1 | ||
} else { | ||
return 0 | ||
} | ||
} | ||
|
||
module.exports = { alphabeticalExtensionComparator } |
28 changes: 28 additions & 0 deletions
28
src/components/sortings/alphabetical-extension-comparator.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { alphabeticalExtensionComparator } from "./alphabetical-extension-comparator" | ||
|
||
describe("the alphabetical extension comparator", () => { | ||
it("sorts by date when the names are identical", () => { | ||
const a = { sortableName: "alpha", metadata: { maven: { timestamp: 1795044005 } } } | ||
const b = { sortableName: "alpha", metadata: { maven: { timestamp: 1695044005 } } } | ||
|
||
expect(alphabeticalExtensionComparator(a, b)).toBeLessThan(0) | ||
expect(alphabeticalExtensionComparator(b, a)).toBeGreaterThan(0) | ||
}) | ||
|
||
it("put extensions with a name ahead of those without", () => { | ||
const a = { sortableName: "alpha" } | ||
const b = {} | ||
|
||
expect(alphabeticalExtensionComparator(a, b)).toBe(-1) | ||
expect(alphabeticalExtensionComparator(b, a)).toBe(1) | ||
}) | ||
|
||
it("sorts alphabetically", () => { | ||
const a = { sortableName: "alpha", metadata: { maven: { timestamp: 1795044005 } } } | ||
const b = { sortableName: "beta", metadata: { maven: { timestamp: 1695044005 } } } | ||
|
||
expect(alphabeticalExtensionComparator(a, b)).toBeLessThan(0) | ||
expect(alphabeticalExtensionComparator(b, a)).toBeGreaterThan(0) | ||
}) | ||
|
||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
import * as React from "react" | ||
import styled from "styled-components" | ||
import Select from "react-select" | ||
import { styles } from "../util/styles/style" | ||
import { timestampExtensionComparator } from "./timestamp-extension-comparator" | ||
import { alphabeticalExtensionComparator } from "./alphabetical-extension-comparator" | ||
|
||
const Title = styled.label` | ||
font-size: var(--font-size-16); | ||
letter-spacing: 0; | ||
color: var(--grey-2); | ||
width: 100px; | ||
text-align: right; | ||
` | ||
|
||
const SortBar = styled.div` | ||
display: flex; | ||
flex-direction: row; | ||
justify-content: flex-end; | ||
align-items: center; | ||
gap: var(--a-small-space); | ||
` | ||
|
||
const Element = styled.form` | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: flex-start; | ||
align-items: flex-start; | ||
gap: 16px; | ||
` | ||
|
||
// Grab CSS variables in javascript | ||
const grey = styles["grey-2"] | ||
|
||
const colourStyles = { | ||
control: styles => ({ | ||
...styles, | ||
borderRadius: 0, | ||
color: grey, | ||
borderColor: grey, | ||
width: "280px", | ||
}), | ||
option: (styles, { isDisabled }) => { | ||
return { | ||
...styles, | ||
cursor: isDisabled ? "not-allowed" : "default", | ||
borderRadius: 0, | ||
} | ||
}, | ||
dropdownIndicator: styles => ({ | ||
...styles, | ||
color: grey, // Custom colour | ||
}), | ||
indicatorSeparator: styles => ({ | ||
...styles, | ||
margin: 0, | ||
backgroundColor: grey, | ||
}), | ||
} | ||
|
||
const sortings = [ | ||
{ label: "most recently released", value: "time", comparator: timestampExtensionComparator }, | ||
{ label: "alphabetical", value: "alpha", comparator: alphabeticalExtensionComparator }] | ||
|
||
const Sortings = ({ sorterAction }) => { | ||
|
||
const setSortByDescription = (entry) => { | ||
// We need to wrap our comparator functions in functions or they get called, which goes very badly | ||
sorterAction && sorterAction(() => entry.comparator) | ||
} | ||
|
||
return ( | ||
<SortBar className="sortings"> | ||
<Title htmlFor="sort">Sort by</Title> | ||
<Element data-testid="sort-form"> | ||
<Select | ||
placeholder="default" | ||
options={sortings} | ||
onChange={label => setSortByDescription(label)} | ||
name="sort" | ||
inputId="sort" | ||
styles={colourStyles} | ||
/> | ||
</Element> | ||
</SortBar> | ||
) | ||
} | ||
|
||
export default Sortings | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import React from "react" | ||
import { render, screen } from "@testing-library/react" | ||
import userEvent from "@testing-library/user-event" | ||
import Sortings from "./sortings" | ||
import selectEvent from "react-select-event" | ||
import { alphabeticalExtensionComparator } from "./alphabetical-extension-comparator" | ||
import { timestampExtensionComparator } from "./timestamp-extension-comparator" | ||
|
||
|
||
let mockQueryParamSearchString = undefined | ||
|
||
jest.mock("react-use-query-param-string", () => { | ||
|
||
const original = jest.requireActual("react-use-query-param-string") | ||
return { | ||
...original, | ||
useQueryParamString: jest.fn().mockImplementation(() => [mockQueryParamSearchString, jest.fn().mockImplementation((val) => mockQueryParamSearchString = val), true]), | ||
getQueryParams: jest.fn().mockReturnValue({ "search-regex": mockQueryParamSearchString }) | ||
|
||
} | ||
}) | ||
|
||
describe("sorting bar", () => { | ||
const sortListener = jest.fn() | ||
|
||
beforeEach(() => { | ||
mockQueryParamSearchString = undefined | ||
render( | ||
<Sortings | ||
sorterAction={sortListener} | ||
/> | ||
) | ||
}) | ||
|
||
afterEach(() => { | ||
jest.clearAllMocks() | ||
}) | ||
|
||
|
||
describe("sorting", () => { | ||
userEvent.setup() | ||
const label = "Sort by" | ||
|
||
it("lets the listener know when a new sort scheme is chosen", async () => { | ||
expect(screen.getByTestId("sort-form")).toHaveFormValues({ | ||
"sort": "", | ||
}) | ||
await selectEvent.select(screen.getByLabelText(label), "most recently released") | ||
|
||
expect(sortListener).toHaveBeenCalled() | ||
}) | ||
|
||
it("lets the listener know when a new timestamp sort scheme is chosen", async () => { | ||
expect(screen.getByTestId("sort-form")).toHaveFormValues({ | ||
"sort": "", | ||
}) | ||
await selectEvent.select(screen.getByLabelText(label), "most recently released") | ||
|
||
expect(sortListener).toHaveBeenCalledWith(expect.any(Function)) | ||
const param = sortListener.mock.calls[0][0] | ||
expect(param()).toEqual(timestampExtensionComparator) | ||
}) | ||
|
||
it("lets the listener know when an alphabetical scheme is chosen", async () => { | ||
expect(screen.getByTestId("sort-form")).toHaveFormValues({ | ||
"sort": "", | ||
}) | ||
await selectEvent.select(screen.getByLabelText(label), "alphabetical") | ||
|
||
expect(sortListener).toHaveBeenCalledWith(expect.any(Function)) | ||
const param = sortListener.mock.calls[0][0] | ||
expect(param()).toEqual(alphabeticalExtensionComparator) | ||
}) | ||
|
||
}) | ||
}) |
Oops, something went wrong.