Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.code.misc;

import io.quarkus.code.model.CodeQuarkusCategory;
import io.quarkus.code.model.CodeQuarkusExtension;
import io.quarkus.code.service.PlatformOverride;
import io.quarkus.maven.dependency.ArtifactCoords;
Expand Down Expand Up @@ -59,7 +60,7 @@ public static CodeQuarkusExtension toCodeQuarkusExtension(
.name(ext.getName())
.description(ext.getDescription())
.shortName(extensionProcessor.getShortName())
.category(cat.getName())
.category(new CodeQuarkusCategory(cat.getId(), cat.getName()))
.tags(platformOverride.extensionTagsMapper(getTags(extensionProcessor)))
.keywords(extensionProcessor.getExtendedKeywords())
.transitiveExtensions(ExtensionProcessor.getMetadataValue(ext, "extension-dependencies").asStringList())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.quarkus.code.model;

import com.fasterxml.jackson.annotation.JsonInclude;

@JsonInclude(JsonInclude.Include.NON_NULL)
public record CodeQuarkusCategory(
String id,
String name) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public record CodeQuarkusExtension(
String name,
String description,
String shortName,
String category,
CodeQuarkusCategory category,
List<String> transitiveExtensions,
List<String> tags,
Set<String> keywords,
Expand Down Expand Up @@ -61,7 +61,7 @@ public static class Builder {
private String name;
private String description;
private String shortName = "";
private String category;
private CodeQuarkusCategory category;
private List<String> tags;
private List<String> transitiveExtensions = List.of();
private Set<String> keywords;
Expand Down Expand Up @@ -105,7 +105,7 @@ public Builder shortName(String shortName) {
return this;
}

public Builder category(String category) {
public Builder category(CodeQuarkusCategory category) {
this.category = category;
return this;
}
Expand Down
7 changes: 6 additions & 1 deletion base/src/main/resources/web/lib/components/api/model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export interface Extension {
tags: string[];
description?: string;
shortName?: string;
category: string;
category: Category;
platform: boolean;
default: boolean;
order: number;
Expand Down Expand Up @@ -72,6 +72,11 @@ export interface JavaCompatibility {
recommended: number;
}

export interface Category {
id: string;
name: string;
}

export interface BuildToolCompatibility {
tools: string[];
recommended: string;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {useHotkeys} from 'react-hotkeys-hook';
import {useAnalytics} from '../../core/analytics';
import {InputProps} from '../../core/types';
import {debouncedComputeResults, FilterResult, ProcessedExtensions, processExtensionsValues} from './extensions-utils';
import {Platform, QuarkusProject} from '../api/model';
import {Category, Platform, QuarkusProject} from '../api/model';
import './extensions-picker.scss';
import {ExtensionRow} from './extension-row';
import {ExtensionSearchBar} from './extension-search-bar';
Expand All @@ -24,7 +24,7 @@ export interface ExtensionEntry {
tags: string[];
description?: string;
shortName?: string;
category: string;
category: Category;
order: number;
default: boolean;
guide?: string;
Expand Down Expand Up @@ -153,7 +153,7 @@ export const ExtensionsPicker = (props: ExtensionsPickerProps) => {
}
}, hotkeysOptions, [entries, keyboardIndex]);

let currentCat: string | undefined;
let currentCat: Category | undefined;

function toggleShowList() {
setKeyboardIndex(-1);
Expand Down Expand Up @@ -209,12 +209,12 @@ export const ExtensionsPicker = (props: ExtensionsPickerProps) => {
layout="picker"
/>
);
if (!result.filtered && (!currentCat || currentCat !== ex.category)) {
if (!result.filtered && (!currentCat || currentCat.id !== ex.category.id)) {
currentCat = ex.category;
return (
<React.Fragment key={i}>
<div className="extension-category">
{currentCat}
{currentCat.name}
</div>
{ext}
</React.Fragment>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import {ExtensionEntry} from './extensions-picker';
import {Extension} from '../api/model';
import {Category, Extension} from '../api/model';
import _ from 'lodash';
import {Analytics} from '../../core/analytics';
import {parse, EqFilter, InFilter, TermFilter, Filter} from "../../core/search";
import {EqFilter, Filter, InFilter, parse, TermFilter} from "../../core/search";

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

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

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

export function processTags(tags: string[]): { [field: string]: string[] } {
const processed: { [field: string]: string[] } = {};
export function processTags(tags: string[]): { [field: string]: FilterOption[] } {
const processed: { [field: string]: FilterOption[] } = {};
for (let tag of tags) {
let key: string, value: string;
if (tag.indexOf(':') > 0) {
Expand All @@ -71,7 +71,7 @@ export function processTags(tags: string[]): { [field: string]: string[] } {
if (!processed[key]) {
processed[key] = [];
}
processed[key].push(value);
processed[key].push({value: value, label: value});
}
return processed;
}
Expand Down Expand Up @@ -214,6 +214,11 @@ export const removeDuplicateIds = (entries: ExtensionEntry[]): ExtensionEntry[]
return _.uniqBy(entries, 'id');
};

export interface FilterOption{
label: string;
value: string;
}

export interface MetadataFilterValues {
radio: boolean;
optional: boolean;
Expand Down Expand Up @@ -280,25 +285,23 @@ export function addStarMetadataFilter(query: string, key: string) {
}


function catToId(category?: string): string {
return category?.toLowerCase().replace(' ', '-').replace(/\s+.+$/i, '');
}

function getMetadataFilters(filters: Filter[], entries: ExtensionEntry[]): MetadataFilters {
const tags = new Set<string>();
const cats = new Set<string>();
const cats = new Map<string, FilterOption>();
for (let entry of entries) {
if (entry.tags) {
for (let tag of entry.tags) {
tags.add(tag);
}
for (let tag of entry.tags) {
tags.add(tag);
}
// Do a uniqueness check here rather than filtering after, since Sets do uniqueness by reference for objects
if (!cats.has(entry.category.id)) {
cats.set(entry.category.id, {label: entry.category.name, value: entry.category.id});
}
}
cats.add(catToId(entry.category))
}
const tagFilters = processTags(Array.from(tags));
tagFilters.category = Array.from(cats);
tagFilters.platform = ['yes', 'no'];

tagFilters.category = [...cats.values()];
tagFilters.platform = toFilterOptions(['yes', 'no']);

const metadataFilters: MetadataFilters = {};

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

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

function toFilterOptions(strings: string[]): FilterOption[] {
return strings.map(s => ( {label: s, value: s}));
}

export function toFilterResult(filters: Filter[], entries: Extension[], filteredEntries: Extension[], filtered: boolean, onResult: (result: FilterResult) => void) {
const result: FilterResult = {
entries: filteredEntries,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export function FilterCombo({
key={idx}
className={classNames('filter-option', item.active ? "active" : "inactive")}
onClick={() => onToggleValue(item.value, item.active)}
aria-label={`${item.active ? 'Remove' : 'Add'} ${label}:${item.label} filter`}
aria-label={`${item.active ? 'Remove' : 'Add'} ${label}:${item.value} filter`}
>
{item.active ? selectIcons[0] : selectIcons[1]}
<span className='label'>{item.label}</span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public void testSearchExtensions(TestInfo testInfo) throws Throwable {
.toList();
refs.forEach(ref -> {
assertThat(platformService.recommendedPlatformInfo().codeQuarkusExtensions()).anyMatch(
e -> e.id().equals(ref.id()) && e.category().equalsIgnoreCase("cloud"));
e -> e.id().equals(ref.id()) && e.category().id().equalsIgnoreCase("cloud"));
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.code.misc;

import io.quarkus.code.model.CodeQuarkusCategory;
import io.quarkus.code.model.CodeQuarkusExtension;
import io.quarkus.code.service.PlatformOverride;
import io.quarkus.registry.catalog.ExtensionCatalog;
Expand Down Expand Up @@ -38,7 +39,7 @@ void textContent() throws IOException {
.name("RESTEasy JAX-RS")
.description("REST endpoint framework implementing JAX-RS and more")
.shortName("jax-rs")
.category("Web")
.category(new CodeQuarkusCategory("web", "Webbed"))
.tags(List.of("with:starter-code", "status:stable"))
.keywords(Set.of("endpoint", "framework", "jax", "jaxrs", "jax-rs", "quarkus-resteasy", "rest",
"resteasy", "web"))
Expand All @@ -55,7 +56,7 @@ void textContent() throws IOException {
.version("5.5.0.1")
.name("Mutiny support for REST Client")
.description("Enable Mutiny for the REST client")
.category("Web")
.category(new CodeQuarkusCategory("web", "Webbed"))
.tags(List.of("status:preview"))
.keywords(Set.of("rest", "reactive", "web", "web-client", "rest-client", "client", "quarkus-rest-client-mutiny",
"microprofile-rest-client", "support", "mutiny", "rest-client-mutiny"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ void downloadAsPostShouldWorkWithAllExtensions() {
var projectDefinition = ProjectDefinition.builder().noCode(true)
.extensions(platformService.recommendedCodeQuarkusExtensions()
.stream()
.filter(extension -> !extension.category().equals("Alternative languages"))
.filter(extension -> !"alt-languages".equals(extension.category().id()))
// Remove this when we use java 25 in quarkus
.filter(extension -> !"io.quarkiverse.langchain4j:quarkus-langchain4j-gpu-llama3"
.equals(extension.id()))
Expand Down
2 changes: 1 addition & 1 deletion base/src/test/resources/fakeextensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -2257,7 +2257,7 @@
} ],
"categories" : [ {
"id" : "web",
"name" : "Web",
"name" : "Webbed",
"description" : "Everything you need for REST endpoints, HTTP and web formats like JSON",
"metadata" : {
"pinned" : [ "io.quarkus:quarkus-resteasy", "io.quarkus:quarkus-resteasy-jackson", "io.quarkus:quarkus-resteasy-jsonb" ]
Expand Down