Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new sort option: last updated #3611

Merged
merged 1 commit into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions database/migrations/functions/packages/search_packages.sql
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ begin
order by
case when v_sort = 'relevance' then (relevance, stars) end desc,
case when v_sort = 'stars' then (stars, relevance) end desc,
case when v_sort = 'last_updated' then (ts, stars) end desc,
official desc,
verified_publisher desc,
name asc
Expand Down
118 changes: 98 additions & 20 deletions database/tests/functions/packages/search_packages.sql
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
-- Start transaction and plan tests
begin;
select plan(30);
select plan(31);

-- Declare some variables
\set user1ID '00000000-0000-0000-0000-000000000001'
Expand Down Expand Up @@ -93,7 +93,7 @@ insert into snapshot (
'digest-package1-1.0.0',
'readme',
'basic install',
'2020-06-16 11:20:34+02'
'2020-06-16 11:20:35+02'
);
insert into snapshot (
package_id,
Expand Down Expand Up @@ -290,7 +290,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -438,7 +438,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -513,7 +513,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -559,7 +559,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -636,7 +636,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -682,7 +682,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -760,7 +760,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -838,7 +838,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -923,7 +923,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1027,7 +1027,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1348,7 +1348,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1399,7 +1399,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1478,7 +1478,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1528,7 +1528,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1609,7 +1609,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1727,7 +1727,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1884,7 +1884,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand Down Expand Up @@ -1962,7 +1962,7 @@ select results_eq(
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299234,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
Expand All @@ -1983,6 +1983,84 @@ select results_eq(
$$,
'Sort: stars TSQueryWeb: kw1 | Packages 2 and 1 expected'
);
select results_eq(
$$
select data::jsonb, total_count::integer from search_packages('{
"ts_query_web": "kw1",
"sort": "last_updated",
"deprecated": true
}')
$$,
$$
values (
'{
"packages": [
{
"package_id": "00000000-0000-0000-0000-000000000001",
"name": "package1",
"normalized_name": "package1",
"category": 1,
"stars": 10,
"official": false,
"cncf": true,
"display_name": "Package 1",
"description": "description",
"logo_image_id": "00000000-0000-0000-0000-000000000001",
"version": "1.0.0",
"app_version": "12.1.0",
"license": "Apache-2.0",
"production_organizations_count": 1,
"ts": 1592299235,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000001",
"kind": 0,
"name": "repo1",
"display_name": "Repo 1",
"url": "https://repo1.com",
"verified_publisher": true,
"official": true,
"cncf": true,
"scanner_disabled": false,
"user_alias": "user1"
}
},
{
"package_id": "00000000-0000-0000-0000-000000000002",
"name": "package2",
"normalized_name": "package2",
"stars": 11,
"official": true,
"display_name": "Package 2",
"description": "description",
"logo_image_id": "00000000-0000-0000-0000-000000000002",
"version": "1.0.0",
"app_version": "12.1.0",
"deprecated": true,
"signed": true,
"signatures": ["cosign"],
"all_containers_images_whitelisted": false,
"production_organizations_count": 0,
"ts": 1592299234,
"repository": {
"repository_id": "00000000-0000-0000-0000-000000000002",
"kind": 0,
"name": "repo2",
"display_name": "Repo 2",
"url": "https://repo2.com",
"verified_publisher": false,
"official": false,
"scanner_disabled": false,
"organization_name": "org1",
"organization_display_name": "Organization 1"
}
}
]
}'::jsonb,
2
)
$$,
'Sort: last_updated TSQueryWeb: kw1 | Packages 1 and 2 expected'
);

-- Finish tests and rollback transaction
select * from finish();
Expand Down
2 changes: 1 addition & 1 deletion docs/api/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5225,7 +5225,7 @@ components:
name: sort
schema:
type: string
enum: ["relevance", "stars"]
enum: ["relevance", "stars", "last_updated"]
example: relevance
required: false
description: Sort criteria
Expand Down
4 changes: 2 additions & 2 deletions internal/pkg/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,8 @@ func (m *Manager) SearchJSON(ctx context.Context, input *hub.SearchPackageInput)
if input.Offset < 0 {
return nil, fmt.Errorf("%w: %s", hub.ErrInvalidInput, "invalid offset (o >= 0)")
}
if input.Sort != "" && input.Sort != "relevance" && input.Sort != "stars" {
return nil, fmt.Errorf("%w: %s", hub.ErrInvalidInput, "invalid sort (relevance|stars)")
if input.Sort != "" && input.Sort != "relevance" && input.Sort != "stars" && input.Sort != "last_updated" {
return nil, fmt.Errorf("%w: %s", hub.ErrInvalidInput, "invalid sort (relevance|stars|last_updated)")
}
for _, alias := range input.Users {
if alias == "" {
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1214,7 +1214,7 @@ func TestSearchJSON(t *testing.T) {
},
},
{
"invalid sort (relevance|stars)",
"invalid sort (relevance|stars|last_updated)",
&hub.SearchPackageInput{
Limit: 10,
Sort: "invalid",
Expand Down
3 changes: 2 additions & 1 deletion web/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
SearchResults,
SecurityReport,
SecurityReportResult,
SortOption,
Stats,
Subscription,
TestWebhook,
Expand Down Expand Up @@ -320,7 +321,7 @@ class API_CLASS {
public searchPackages(query: SearchQuery, facets: boolean = true): Promise<SearchResults> {
const q = getURLSearchParams(query);
q.set('facets', facets ? 'true' : 'false');
q.set('sort', query.sort || 'relevance');
q.set('sort', query.sort || SortOption.Relevance);
q.set('limit', query.limit.toString());
q.set('offset', query.offset.toString());

Expand Down
2 changes: 1 addition & 1 deletion web/src/layout/search/SortOptions.module.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.select {
height: 26px !important;
width: 118px !important;
width: 135px !important;
line-height: 1rem !important;
padding-left: 0.75rem !important;
border-color: var(--color-1-500) !important;
Expand Down
20 changes: 13 additions & 7 deletions web/src/layout/search/SortOptions.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
import { isNull } from 'lodash';
import { ChangeEvent, useEffect, useRef } from 'react';

import capitalizeFirstLetter from '../../utils/capitalizeFirstLetter';
import { SortOption } from '../../types';
import styles from './SortOptions.module.css';

interface Props {
activeSort: string;
updateSort: (value: string) => void;
activeSort: SortOption;
updateSort: (value: SortOption) => void;
disabled: boolean;
}

const DEFAULT_SORT = 'relevance';
const SORT_OPTS = [DEFAULT_SORT, 'stars'];
const DEFAULT_SORT = SortOption.Relevance;
const SORT_OPTS = Object.values(SortOption);

const SortOptions = (props: Props) => {
const selectEl = useRef<HTMLSelectElement>(null);

const handleChange = (event: ChangeEvent<HTMLSelectElement>) => {
props.updateSort(event.target.value);
props.updateSort(event.target.value as SortOption);
forceBlur();
};

Expand All @@ -27,6 +27,12 @@ const SortOptions = (props: Props) => {
}
};

const getSortOptionKey = (value: string): string => {
const index = Object.values(SortOption).indexOf(value as unknown as SortOption);
const key = Object.keys(SortOption)[index];
return key;
};

useEffect(() => {
if (!SORT_OPTS.includes(props.activeSort)) {
props.updateSort(DEFAULT_SORT);
Expand All @@ -46,7 +52,7 @@ const SortOptions = (props: Props) => {
>
{SORT_OPTS.map((value: string) => (
<option key={`sort_${value}`} value={value}>
{capitalizeFirstLetter(value)}
{getSortOptionKey(value)}
</option>
))}
;
Expand Down
Loading
Loading