Skip to content

Commit ddfb5a9

Browse files
committed
Use category name as label and id as query parameter
1 parent 85eb11d commit ddfb5a9

10 files changed

Lines changed: 59 additions & 35 deletions

File tree

base/src/main/java/io/quarkus/code/misc/QuarkusExtensionUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.quarkus.code.misc;
22

3+
import io.quarkus.code.model.CodeQuarkusCategory;
34
import io.quarkus.code.model.CodeQuarkusExtension;
45
import io.quarkus.code.service.PlatformOverride;
56
import io.quarkus.maven.dependency.ArtifactCoords;
@@ -59,7 +60,7 @@ public static CodeQuarkusExtension toCodeQuarkusExtension(
5960
.name(ext.getName())
6061
.description(ext.getDescription())
6162
.shortName(extensionProcessor.getShortName())
62-
.category(cat.getName())
63+
.category(new CodeQuarkusCategory(cat.getId(), cat.getName()))
6364
.tags(platformOverride.extensionTagsMapper(getTags(extensionProcessor)))
6465
.keywords(extensionProcessor.getExtendedKeywords())
6566
.transitiveExtensions(ExtensionProcessor.getMetadataValue(ext, "extension-dependencies").asStringList())
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package io.quarkus.code.model;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
5+
@JsonInclude(JsonInclude.Include.NON_NULL)
6+
public record CodeQuarkusCategory(
7+
String id,
8+
String name) {
9+
}

base/src/main/java/io/quarkus/code/model/CodeQuarkusExtension.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public record CodeQuarkusExtension(
1414
String name,
1515
String description,
1616
String shortName,
17-
String category,
17+
CodeQuarkusCategory category,
1818
List<String> transitiveExtensions,
1919
List<String> tags,
2020
Set<String> keywords,
@@ -61,7 +61,7 @@ public static class Builder {
6161
private String name;
6262
private String description;
6363
private String shortName = "";
64-
private String category;
64+
private CodeQuarkusCategory category;
6565
private List<String> tags;
6666
private List<String> transitiveExtensions = List.of();
6767
private Set<String> keywords;
@@ -105,7 +105,7 @@ public Builder shortName(String shortName) {
105105
return this;
106106
}
107107

108-
public Builder category(String category) {
108+
public Builder category(CodeQuarkusCategory category) {
109109
this.category = category;
110110
return this;
111111
}

base/src/main/resources/web/lib/components/api/model.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export interface Extension {
3737
tags: string[];
3838
description?: string;
3939
shortName?: string;
40-
category: string;
40+
category: Category;
4141
platform: boolean;
4242
default: boolean;
4343
order: number;
@@ -72,6 +72,11 @@ export interface JavaCompatibility {
7272
recommended: number;
7373
}
7474

75+
export interface Category {
76+
id: string;
77+
name: string;
78+
}
79+
7580
export interface BuildToolCompatibility {
7681
tools: string[];
7782
recommended: string;

base/src/main/resources/web/lib/components/extensions-picker/extensions-picker.tsx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {useHotkeys} from 'react-hotkeys-hook';
33
import {useAnalytics} from '../../core/analytics';
44
import {InputProps} from '../../core/types';
55
import {debouncedComputeResults, FilterResult, ProcessedExtensions, processExtensionsValues} from './extensions-utils';
6-
import {Platform, QuarkusProject} from '../api/model';
6+
import {Category, Platform, QuarkusProject} from '../api/model';
77
import './extensions-picker.scss';
88
import {ExtensionRow} from './extension-row';
99
import {ExtensionSearchBar} from './extension-search-bar';
@@ -24,7 +24,7 @@ export interface ExtensionEntry {
2424
tags: string[];
2525
description?: string;
2626
shortName?: string;
27-
category: string;
27+
category: Category;
2828
order: number;
2929
default: boolean;
3030
guide?: string;
@@ -153,7 +153,7 @@ export const ExtensionsPicker = (props: ExtensionsPickerProps) => {
153153
}
154154
}, hotkeysOptions, [entries, keyboardIndex]);
155155

156-
let currentCat: string | undefined;
156+
let currentCat: Category | undefined;
157157

158158
function toggleShowList() {
159159
setKeyboardIndex(-1);
@@ -209,12 +209,12 @@ export const ExtensionsPicker = (props: ExtensionsPickerProps) => {
209209
layout="picker"
210210
/>
211211
);
212-
if (!result.filtered && (!currentCat || currentCat !== ex.category)) {
212+
if (!result.filtered && (!currentCat || currentCat.id !== ex.category.id)) {
213213
currentCat = ex.category;
214214
return (
215215
<React.Fragment key={i}>
216216
<div className="extension-category">
217-
{currentCat}
217+
{currentCat.name}
218218
</div>
219219
{ext}
220220
</React.Fragment>

base/src/main/resources/web/lib/components/extensions-picker/extensions-utils.ts

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import {ExtensionEntry} from './extensions-picker';
2-
import {Extension} from '../api/model';
2+
import {Category, Extension} from '../api/model';
33
import _ from 'lodash';
44
import {Analytics} from '../../core/analytics';
5-
import {parse, EqFilter, InFilter, TermFilter, Filter} from "../../core/search";
5+
import {EqFilter, Filter, InFilter, parse, TermFilter} from "../../core/search";
66

77
type ExtensionFieldValueSupplier = (e: Extension) => string | string[] | undefined
88

@@ -25,7 +25,7 @@ const FIELD_IDENTIFIERS: ExtensionFieldIdentifier[] = [
2525
{keys: ['keywords', 'keyword'], valueSupplier: e => e.keywords},
2626
{keys: ['tags', 'tag'], valueSupplier: e => e.tags},
2727
{keys: ['platform', 'p'], valueSupplier: e => e.platform ? 'yes' : 'no'},
28-
{keys: ['category', 'cat'], valueSupplier: e => catToId(e.category)},
28+
{keys: ['category', 'cat'], valueSupplier: e => e.category?.id},
2929
];
3030

3131
const FIELD_KEYS = FIELD_IDENTIFIERS.map(s => s.keys).reduce((acc, value) => acc.concat(value), [])
@@ -53,8 +53,8 @@ export function getAllKeys(extensions: Extension[]): string[] {
5353
return Array.from(keys);
5454
}
5555

56-
export function processTags(tags: string[]): { [field: string]: string[] } {
57-
const processed: { [field: string]: string[] } = {};
56+
export function processTags(tags: string[]): { [field: string]: FilterOption[] } {
57+
const processed: { [field: string]: FilterOption[] } = {};
5858
for (let tag of tags) {
5959
let key: string, value: string;
6060
if (tag.indexOf(':') > 0) {
@@ -71,7 +71,7 @@ export function processTags(tags: string[]): { [field: string]: string[] } {
7171
if (!processed[key]) {
7272
processed[key] = [];
7373
}
74-
processed[key].push(value);
74+
processed[key].push({value: value, label: value});
7575
}
7676
return processed;
7777
}
@@ -214,6 +214,11 @@ export const removeDuplicateIds = (entries: ExtensionEntry[]): ExtensionEntry[]
214214
return _.uniqBy(entries, 'id');
215215
};
216216

217+
export interface FilterOption{
218+
label: string;
219+
value: string;
220+
}
221+
217222
export interface MetadataFilterValues {
218223
radio: boolean;
219224
optional: boolean;
@@ -280,25 +285,23 @@ export function addStarMetadataFilter(query: string, key: string) {
280285
}
281286

282287

283-
function catToId(category?: string): string {
284-
return category?.toLowerCase().replace(' ', '-').replace(/\s+.+$/i, '');
285-
}
286-
287288
function getMetadataFilters(filters: Filter[], entries: ExtensionEntry[]): MetadataFilters {
288289
const tags = new Set<string>();
289-
const cats = new Set<string>();
290+
const cats = new Map<string, FilterOption>();
290291
for (let entry of entries) {
291292
if (entry.tags) {
292-
for (let tag of entry.tags) {
293-
tags.add(tag);
294-
}
293+
for (let tag of entry.tags) {
294+
tags.add(tag);
295+
}
296+
// Do a uniqueness check here rather than filtering after, since Sets do uniqueness by reference for objects
297+
if (!cats.has(entry.category.id)) {
298+
cats.set(entry.category.id, {label: entry.category.name, value: entry.category.id});
299+
}
295300
}
296-
cats.add(catToId(entry.category))
297301
}
298302
const tagFilters = processTags(Array.from(tags));
299-
tagFilters.category = Array.from(cats);
300-
tagFilters.platform = ['yes', 'no'];
301-
303+
tagFilters.category = [...cats.values()];
304+
tagFilters.platform = toFilterOptions(['yes', 'no']);
302305

303306
const metadataFilters: MetadataFilters = {};
304307

@@ -308,8 +311,9 @@ function getMetadataFilters(filters: Filter[], entries: ExtensionEntry[]): Metad
308311
let any = filterForTag?.values?.includes('*') && !filterForTag.negated;
309312
let exclude = filterForTag?.values?.includes('*') && filterForTag.negated;
310313
metadataFilters[key] = {all: [], active: [], inactive: [], any, exclude, radio: RADIO_FILTER_PREDICATE(key), optional: OPTIONAL_FILTER_PREDICATE(key)};
311-
for (let value of tagFilters[key]) {
312-
let label = value;
314+
for (let entry of tagFilters[key]) {
315+
let label = entry.label;
316+
let value = entry.value;
313317
let active = !filterForTag.negated && (filterForTag?.values?.includes(value) || any);
314318

315319
if (active) {
@@ -325,6 +329,10 @@ function getMetadataFilters(filters: Filter[], entries: ExtensionEntry[]): Metad
325329
return metadataFilters;
326330
}
327331

332+
function toFilterOptions(strings: string[]): FilterOption[] {
333+
return strings.map(s => ( {label: s, value: s}));
334+
}
335+
328336
export function toFilterResult(filters: Filter[], entries: Extension[], filteredEntries: Extension[], filtered: boolean, onResult: (result: FilterResult) => void) {
329337
const result: FilterResult = {
330338
entries: filteredEntries,

base/src/main/resources/web/lib/components/extensions-picker/filter-combo.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ export function FilterCombo({
5353
key={idx}
5454
className={classNames('filter-option', item.active ? "active" : "inactive")}
5555
onClick={() => onToggleValue(item.value, item.active)}
56-
aria-label={`${item.active ? 'Remove' : 'Add'} ${label}:${item.label} filter`}
56+
aria-label={`${item.active ? 'Remove' : 'Add'} ${label}:${item.value} filter`}
5757
>
5858
{item.active ? selectIcons[0] : selectIcons[1]}
5959
<span className='label'>{item.label}</span>

base/src/test/java/io/quarkus/code/CodeQuarkusPlaywrightTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ public void testSearchExtensions(TestInfo testInfo) throws Throwable {
106106
.toList();
107107
refs.forEach(ref -> {
108108
assertThat(platformService.recommendedPlatformInfo().codeQuarkusExtensions()).anyMatch(
109-
e -> e.id().equals(ref.id()) && e.category().equalsIgnoreCase("cloud"));
109+
e -> e.id().equals(ref.id()) && e.category().id().equalsIgnoreCase("cloud"));
110110
});
111111
});
112112

base/src/test/java/io/quarkus/code/misc/QuarkusExtensionUtilsTest.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package io.quarkus.code.misc;
22

3+
import io.quarkus.code.model.CodeQuarkusCategory;
34
import io.quarkus.code.model.CodeQuarkusExtension;
45
import io.quarkus.code.service.PlatformOverride;
56
import io.quarkus.registry.catalog.ExtensionCatalog;
@@ -38,7 +39,7 @@ void textContent() throws IOException {
3839
.name("RESTEasy JAX-RS")
3940
.description("REST endpoint framework implementing JAX-RS and more")
4041
.shortName("jax-rs")
41-
.category("Web")
42+
.category(new CodeQuarkusCategory("web", "Webbed"))
4243
.tags(List.of("with:starter-code", "status:stable"))
4344
.keywords(Set.of("endpoint", "framework", "jax", "jaxrs", "jax-rs", "quarkus-resteasy", "rest",
4445
"resteasy", "web"))
@@ -55,7 +56,7 @@ void textContent() throws IOException {
5556
.version("5.5.0.1")
5657
.name("Mutiny support for REST Client")
5758
.description("Enable Mutiny for the REST client")
58-
.category("Web")
59+
.category(new CodeQuarkusCategory("web", "Webbed"))
5960
.tags(List.of("status:preview"))
6061
.keywords(Set.of("rest", "reactive", "web", "web-client", "rest-client", "client", "quarkus-rest-client-mutiny",
6162
"microprofile-rest-client", "support", "mutiny", "rest-client-mutiny"))

base/src/test/resources/fakeextensions.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2257,7 +2257,7 @@
22572257
} ],
22582258
"categories" : [ {
22592259
"id" : "web",
2260-
"name" : "Web",
2260+
"name" : "Webbed",
22612261
"description" : "Everything you need for REST endpoints, HTTP and web formats like JSON",
22622262
"metadata" : {
22632263
"pinned" : [ "io.quarkus:quarkus-resteasy", "io.quarkus:quarkus-resteasy-jackson", "io.quarkus:quarkus-resteasy-jsonb" ]

0 commit comments

Comments
 (0)