web.lib.components.extensions-picker.extensions-picker.tsx Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of code-quarkus Show documentation
Show all versions of code-quarkus Show documentation
Customize a Web Interface to generate Quarkus starter projects.
import * as React from 'react';
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 './extensions-picker.scss';
import {ExtensionRow} from './extension-row';
import {ExtensionSearchBar} from './extension-search-bar';
import {Button} from 'react-bootstrap';
import {FaAngleDown, FaAngleLeft, FaAngleRight, FaRocket} from 'react-icons/fa';
import {SearchResultsInfo} from './search-results-info';
import {PresetsPanel} from "./presets-panel";
import _ from 'lodash';
import {SelectedExtensions} from "./selected-extensions";
export interface ExtensionEntry {
id: string;
name: string;
version: string;
keywords: string[];
transitiveExtensions: string[];
tags: string[];
description?: string;
shortName?: string;
category: string;
order: number;
default: boolean;
guide?: string;
bom?: string
platform: boolean;
}
export interface TagEntry {
name: string;
href?: string;
description?: string;
color?: string;
hide?: boolean;
}
export interface ExtensionsPickerValue {
extensions: ExtensionEntry[];
}
const REDUCED_SIZE = 100;
interface ExtensionsPickerProps extends InputProps {
tagsDef: TagEntry[];
placeholder: string;
buildTool: string;
project?: QuarkusProject;
platform: Platform;
filter: string;
setFilter: React.Dispatch>;
filterFunction?(d: ExtensionEntry): boolean;
}
const hotkeysOptions = {
ignoreEventWhen: (e) => {
const el = (e.target) as any | undefined;
if (!el) {
return false;
}
const tagName = el && el.tagName;
return !(el.id === 'extensions-search-input' || tagName !== 'INPUT');
},
enableOnFormTags: ['INPUT'] as 'INPUT'[]
};
export const ExtensionsPicker = (props: ExtensionsPickerProps) => {
const {filter} = props;
const [processedExtensions, setProcessedExtensions] = React.useState(undefined);
const [keyboardActivated, setKeyBoardActivated] = React.useState(-1);
const [showList, setShowList] = React.useState(false);
const [showAll, setShowAll] = React.useState(false);
const [result, setResult] = React.useState();
const analytics = useAnalytics();
const context = {element: 'extension-picker'};
function setFilter(filter: string) {
setKeyBoardActivated(-1);
setShowAll(false);
setShowList(false);
props.setFilter(filter);
}
const extensions = props.value.extensions || [];
const entrySet = new Set(extensions.map(e => e.id));
const entriesById: Map = new Map(props.platform.extensions.map(item => [item.id, item]));
React.useEffect(() => {
setProcessedExtensions(processExtensionsValues(props.platform.extensions));
}, [props.platform.extensions, setProcessedExtensions]);
React.useEffect(() => {
debouncedComputeResults(analytics, filter, props.platform.extensions, processedExtensions, setResult);
}, [filter, processedExtensions, props.platform.extensions, setShowAll, setResult]);
const allEntries = result?.effective || [];
const entries = showAll ? allEntries : allEntries.slice(0, REDUCED_SIZE)
const addById = (id: string, type: string) => {
entrySet.add(id);
props.onChange({extensions: Array.from(entrySet).map(e => entriesById.get(e)!)});
analytics.event('Select extension', {extension: id, type, ...context});
};
const add = (index: number, type: string) => {
const id = entries[index].id;
addById(id, type);
if (keyboardActivated >= 0) {
setKeyBoardActivated(index);
}
};
const remove = (id: string, type: string) => {
entrySet.delete(id);
props.onChange({extensions: Array.from(entrySet).map(e => entriesById.get(e)!)});
analytics.event('Unselect extension', {extension: id, type, ...context});
};
const flip = (index: number, origin: string) => {
if (!entries[index] || entries[index].default) {
return;
}
if (entrySet.has(entries[index].id)) {
remove(entries[index].id, origin);
} else {
add(index, origin);
}
};
useHotkeys('esc', () => setKeyBoardActivated(-1), hotkeysOptions);
useHotkeys('up', () => {
setKeyBoardActivated((prev) => Math.max(0, prev - 1))
}, hotkeysOptions);
useHotkeys('down', () => setKeyBoardActivated((prev) => Math.min(entries.length - 1, prev + 1)), hotkeysOptions, [entries]);
useHotkeys('space', (event) => {
if (keyboardActivated >= 0) {
event.preventDefault();
flip(keyboardActivated, 'Keyboard');
}
}, hotkeysOptions, [entries, keyboardActivated]);
let currentCat: string | undefined;
function toggleShowList() {
setKeyBoardActivated(-1);
setShowList(!showList);
}
function removeById(id: string, type: string) {
props.onChange({extensions: _.filter(props.value.extensions, e => e.id !== id && id !== '*')});
analytics.event('Unselect extension', {extension: id, type, element: 'extension-picker'});
}
return (
{!result?.filtered && !showList ? (
{props.project.extensions.length === 0 ?
:
}
) : (
{!result?.filtered &&
}
{entries.map((ex, i) => {
const ext = (
flip(i, 'List')}
buildTool={props.buildTool}
layout="picker"
/>
);
if (!result.filtered && (!currentCat || currentCat !== ex.category)) {
currentCat = ex.category;
return (
{currentCat}
{ext}
);
}
return ext;
})}
{!showAll && allEntries.length > 100 &&
}
)}
);
};
© 2015 - 2025 Weber Informatics LLC | Privacy Policy