Skip to content

Commit

Permalink
Improve filters to support more foundations
Browse files Browse the repository at this point in the history
Signed-off-by: Sergio Castaño Arteaga <[email protected]>
Signed-off-by: Cintia Sanchez Garcia <[email protected]>
Co-authored-by: Sergio Castaño Arteaga <[email protected]>
Co-authored-by: Cintia Sanchez Garcia <[email protected]>
  • Loading branch information
tegioz and cynthia-sg committed Feb 9, 2024
1 parent 157b659 commit ffba978
Show file tree
Hide file tree
Showing 10 changed files with 353 additions and 220 deletions.
247 changes: 135 additions & 112 deletions database/migrations/functions/issues/get_issues_filters.sql
Original file line number Diff line number Diff line change
@@ -1,123 +1,146 @@
-- Return the filters that can be used when searching for issues in json format.
create or replace function get_issues_filters()
returns json as $$
select json_build_array(
json_build_object(
'title', 'Foundation',
'key', 'foundation',
'options', (
select coalesce(json_agg(json_build_object(
'name', display_name,
'value', foundation_id
)), '[]')
from (
select foundation_id, display_name
from foundation
order by foundation_id asc
) f
)
select json_build_object(
'filters', json_build_array(
json_build_object(
'title', 'Foundation',
'key', 'foundation',
'options', (
select coalesce(json_agg(json_build_object(
'name', display_name,
'value', foundation_id
)), '[]')
from (
select foundation_id, display_name
from foundation
order by foundation_id asc
) f
)
),
json_build_object(
'title', 'Maturity',
'key', 'maturity',
'options', (
select coalesce(json_agg(json_build_object(
'name', initcap(maturity),
'value', maturity
)), '[]')
from (
select distinct maturity
from project
where maturity is not null
order by maturity asc
) m
)
),
json_build_object(
'title', 'Project',
'key', 'project',
'options', (
select coalesce(json_agg(json_build_object(
'name', coalesce(display_name, name),
'value', name
)), '[]')
from (
select distinct p.display_name, p.name
from project p
join repository r using (project_id)
join issue i using (repository_id)
order by name asc
) m
)
),
json_build_object(
'title', 'Area',
'key', 'area',
'options', (
select coalesce(json_agg(json_build_object(
'name', initcap(area::text),
'value', area::text
)), '[]')
from (
select unnest(enum_range(null::area)) as area
) a
)
),
json_build_object(
'title', 'Kind',
'key', 'kind',
'options', (
select coalesce(json_agg(json_build_object(
'name', initcap(kind::text),
'value', kind::text
)), '[]')
from (
select unnest(enum_range(null::kind)) as kind
) k
)
),
json_build_object(
'title', 'Difficulty',
'key', 'difficulty',
'options', (
select coalesce(json_agg(json_build_object(
'name', initcap(difficulty::text),
'value', difficulty::text
)), '[]')
from (
select unnest(enum_range(null::difficulty)) as difficulty
) d
)
),
json_build_object(
'title', 'Language',
'key', 'language',
'options', (
select coalesce(json_agg(json_build_object(
'name', language,
'value', language
)), '[]')
from (
select distinct(unnest(languages)) as language
from repository
order by language asc
) m
)
),
'{
"title": "Other",
"options": [
{
"name": "Good first issue",
"key": "good_first_issue",
"type": "boolean"
},
{
"name": "Mentor available",
"key": "mentor_available",
"type": "boolean"
}
]
}'::jsonb
),
json_build_object(
'title', 'Maturity',
'key', 'maturity',
'options', (
select coalesce(json_agg(json_build_object(
'name', initcap(maturity),
'value', maturity
)), '[]')
'extra', json_build_object(
'maturity', (
select coalesce(json_object_agg(foundation_id, maturities), '{}')
from (
select distinct maturity
select distinct foundation_id, array_agg(distinct maturity) as maturities
from project
where maturity is not null
order by maturity asc
) m
)
),
json_build_object(
'title', 'Project',
'key', 'project',
'options', (
select coalesce(json_agg(json_build_object(
'name', coalesce(display_name, name),
'value', name
)), '[]')
from (
select distinct p.display_name, p.name
from project p
join repository r using (project_id)
join issue i using (repository_id)
order by name asc
) m
)
),
json_build_object(
'title', 'Area',
'key', 'area',
'options', (
select coalesce(json_agg(json_build_object(
'name', initcap(area::text),
'value', area::text
)), '[]')
from (
select unnest(enum_range(null::area)) as area
) a
)
),
json_build_object(
'title', 'Kind',
'key', 'kind',
'options', (
select coalesce(json_agg(json_build_object(
'name', initcap(kind::text),
'value', kind::text
)), '[]')
from (
select unnest(enum_range(null::kind)) as kind
) k
)
),
json_build_object(
'title', 'Difficulty',
'key', 'difficulty',
'options', (
select coalesce(json_agg(json_build_object(
'name', initcap(difficulty::text),
'value', difficulty::text
)), '[]')
from (
select unnest(enum_range(null::difficulty)) as difficulty
) d
)
),
json_build_object(
'title', 'Language',
'key', 'language',
'options', (
select coalesce(json_agg(json_build_object(
'name', language,
'value', language
)), '[]')
group by foundation_id
order by foundation_id asc
) as maturities
),
'project', (
select coalesce(json_object_agg(foundation_id, projects), '{}')
from (
select distinct(unnest(languages)) as language
from repository
order by language asc
) m
select distinct foundation_id, array_agg(distinct name) as projects
from project
group by foundation_id
order by foundation_id asc
) as projects
)
),
'{
"title": "Other",
"options": [
{
"name": "Good first issue",
"key": "good_first_issue",
"type": "boolean"
},
{
"name": "Mentor available",
"key": "mentor_available",
"type": "boolean"
}
]
}'::jsonb
)
);
$$ language sql;
2 changes: 1 addition & 1 deletion web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"license": "Apache-2.0",
"dependencies": {
"classnames": "^2.5.1",
"clo-ui": "https://github.com/cncf/clo-ui.git#v0.1.22",
"clo-ui": "https://github.com/cncf/clo-ui.git#v0.2.0",
"lodash": "^4.17.21",
"moment": "^2.30.1",
"react": "^18.2.0",
Expand Down
4 changes: 2 additions & 2 deletions web/src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { isEmpty, isNull, isUndefined } from 'lodash';
import isArray from 'lodash/isArray';

import { DEFAULT_SORT_BY } from '../data';
import { Error, ErrorKind, Filter, Issue, SearchQuery } from '../types';
import { Error, ErrorKind, FiltersReponse, Issue, SearchQuery } from '../types';

interface FetchOptions {
method: 'POST' | 'GET' | 'PUT' | 'DELETE' | 'HEAD';
Expand Down Expand Up @@ -104,7 +104,7 @@ class API_CLASS {
.catch((error) => Promise.reject(error));
}

public getIssuesFilters(): Promise<Filter[]> {
public getIssuesFilters(): Promise<FiltersReponse> {
return this.apiFetch({
url: `${this.API_BASE_URL}/filters/issues`,
});
Expand Down
8 changes: 1 addition & 7 deletions web/src/layout/common/Card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ const Card = (props: Props) => {
maturityLevel={props.issue.project.maturity}
maxLength={14}
className="d-none d-sm-flex me-2"
onClick={() => searchByFilter(FilterKind.Maturity, props.issue.project.maturity!)}
/>
)}
<FoundationBadge
Expand Down Expand Up @@ -210,12 +209,7 @@ const Card = (props: Props) => {
onClick={() => searchByFilter(FilterKind.Foundation, props.issue.project.foundation)}
/>
{props.issue.project.maturity && (
<MaturityBadge
maturityLevel={props.issue.project.maturity}
className="ms-2"
maxLength={14}
onClick={() => searchByFilter(FilterKind.Maturity, props.issue.project.maturity!)}
/>
<MaturityBadge maturityLevel={props.issue.project.maturity} className="ms-2" maxLength={14} />
)}
</div>

Expand Down
16 changes: 13 additions & 3 deletions web/src/layout/search/Filters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { isEmpty } from 'lodash';
import React from 'react';
import { IoMdCloseCircleOutline } from 'react-icons/io';

import { FilterKind } from '../../types';

interface Props {
visibleTitle: boolean;
filters: FilterSection[];
Expand All @@ -14,6 +16,7 @@ interface Props {
onChange: (name: string, value: string, checked: boolean, type?: string) => void;
onResetFilters?: () => void;
device: string;
disabledSections: FilterKind[];
}

const Filters = (props: Props) => {
Expand Down Expand Up @@ -47,10 +50,17 @@ const Filters = (props: Props) => {

{props.filters.map((section: FilterSection) => {
const activeFilters = section.key ? props.activeFilters[section.key] : getActiveFiltersForOther();
// Does not render project and language filters on mobile version
if (section.key && ['project', 'language'].includes(section.key)) return null;
const key = (section.key || section.title) as FilterKind;
// Does not render project and language filters or disabled sections on mobile version
if (
[FilterKind.Language, FilterKind.Project].includes(key) ||
props.disabledSections.includes(key) ||
section.options.length === 0
)
return null;

return (
<React.Fragment key={`sec_${section.key}`}>
<React.Fragment key={`sec_${key}`}>
<FiltersSection
device={props.device}
activeFilters={activeFilters}
Expand Down
4 changes: 4 additions & 0 deletions web/src/layout/search/FiltersInLine.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@
max-height: 300px;
}

.tooltipArrow {
margin-top: 7px;
}

.dropdown label {
font-size: 0.8rem;
}
Expand Down
Loading

0 comments on commit ffba978

Please sign in to comment.