Merge pull request #17559 from antoniobergas/feat/microsite-plugins-dropdown-filter

 feat(pluginsFilter): added dropdown filter for plugins list
This commit is contained in:
Ben Lambert
2023-05-18 15:02:26 +02:00
committed by GitHub
4 changed files with 221 additions and 44 deletions
@@ -0,0 +1,36 @@
import { ChipCategory } from '@site/src/util/types';
import React from 'react';
type Props = {
categories: ChipCategory[];
handleChipClick: (name: string) => void;
};
const PluginsFilter = ({ categories, handleChipClick }: Props) => {
return (
<div className="dropdown dropdown--hoverable">
<button className="button button--info dropdown__toggle">
Categories Filter
</button>
<ul className="dropdown__menu">
{categories.map(chip => {
return (
<li key={chip.name} onClick={() => handleChipClick(chip.name)}>
<div className="dropdown__item">
<input
type="checkbox"
className="dropdown__checkbox"
checked={chip.isSelected}
onChange={() => handleChipClick(chip.name)}
/>
<span className="dropdown__label">{chip.name}</span>
</div>
</li>
);
})}
</ul>
</div>
);
};
export default PluginsFilter;
+130 -43
View File
@@ -1,13 +1,13 @@
import Link from '@docusaurus/Link';
import Layout from '@theme/Layout';
import clsx from 'clsx';
import React from 'react';
import React, { useState } from 'react';
import { IPluginData, PluginCard } from './_pluginCard';
import pluginsStyles from './plugins.module.scss';
import { ChipCategory } from '@site/src/util/types';
import { truncateDescription } from '@site/src/util/truncateDescription';
import PluginsFilter from '@site/src/components/pluginsFilter/pluginsFilter';
//#region Plugin data import
const pluginsContext = require.context(
'../../../data/plugins',
false,
@@ -29,50 +29,137 @@ const plugins = pluginsContext.keys().reduce(
plugins.corePlugins.sort((a, b) => a.order - b.order);
plugins.otherPlugins.sort((a, b) => a.order - b.order);
//#endregion
const Plugins = () => (
<Layout>
<div
className={clsx('container', 'padding--lg', pluginsStyles.pluginsPage)}
>
<div className="marketplaceBanner">
<div className="marketplaceContent">
<h2>Plugin Marketplace</h2>
const Plugins = () => {
const allCategoriesSet = new Set(
[...plugins.corePlugins, ...plugins.otherPlugins].map(
({ category }) => category,
),
);
const allCategoriesArray = Array.from(allCategoriesSet).map(category => ({
name: category,
isSelected: false,
}));
const [categories, setCategories] =
useState<ChipCategory[]>(allCategoriesArray);
const [selectedCategories, setSelectedCategories] = useState<string[]>([]);
const [showCoreFeatures, setShowCoreFeatures] = useState(true);
const [showOtherPlugins, setShowOtherPlugins] = useState(true);
<p>
Open source plugins that you can add to your Backstage deployment.
Learn how to build a <Link to="/docs/plugins">plugin</Link>.
</p>
const handleChipClick = (categoryName: string) => {
const isSelected =
categories.find(category => category.name === categoryName)?.isSelected ||
false;
const newSelectedCategories = isSelected
? selectedCategories.filter(c => c !== categoryName)
: [...selectedCategories, categoryName];
setSelectedCategories(newSelectedCategories);
const newCategories = categories.map(category => {
if (category.name === categoryName) {
return { ...category, isSelected: !isSelected };
}
return category;
});
setCategories(newCategories);
if (!newSelectedCategories.includes('Core Feature')) {
setShowCoreFeatures(false);
} else {
setShowCoreFeatures(true);
}
if (
newSelectedCategories.length === 1 &&
newSelectedCategories[0] === 'Core Feature'
) {
setShowOtherPlugins(false);
} else {
setShowOtherPlugins(true);
}
if (newSelectedCategories.length === 0) {
setShowOtherPlugins(true);
setShowCoreFeatures(true);
}
};
return (
<Layout>
<div
className={clsx('container', 'padding--lg', pluginsStyles.pluginsPage)}
>
<div className="marketplaceBanner">
<div className="marketplaceContent">
<h2>Plugin Marketplace</h2>
<p>
Open source plugins that you can add to your Backstage deployment.
Learn how to build a <Link to="/docs/plugins">plugin</Link>.
</p>
</div>
<Link
to="/docs/plugins/add-to-marketplace"
className="button button--outline button--primary"
>
Add to Marketplace
</Link>
</div>
<Link
to="/docs/plugins/add-to-marketplace"
className="button button--outline button--primary"
>
Add to Marketplace
</Link>
<div className="bulletLine margin-bottom--lg"></div>
<div className="pluginsFilterBox">
<PluginsFilter
categories={categories}
handleChipClick={handleChipClick}
/>
</div>
{showCoreFeatures && (
<div>
<h2>Core Features</h2>
<div className="pluginsContainer margin-bottom--lg">
{plugins.corePlugins
.filter(
pluginData =>
!selectedCategories.length ||
selectedCategories.includes(pluginData.category),
)
.map(pluginData => (
<PluginCard
key={pluginData.title}
{...pluginData}
></PluginCard>
))}
</div>
</div>
)}
{showOtherPlugins && (
<div>
<h2>All Plugins</h2>
<div className="pluginsContainer margin-bottom--lg">
{plugins.otherPlugins
.filter(
pluginData =>
!selectedCategories.length ||
selectedCategories.includes(pluginData.category),
)
.map(pluginData => (
<PluginCard
key={pluginData.title}
{...pluginData}
></PluginCard>
))}
</div>
</div>
)}
</div>
<div className="bulletLine margin-bottom--lg"></div>
<h2>Core Features</h2>
<div className="pluginsContainer margin-bottom--lg">
{plugins.corePlugins.map(pluginData => (
<PluginCard key={pluginData.title} {...pluginData}></PluginCard>
))}
</div>
<h2>All Plugins</h2>
<div className="pluginsContainer margin-bottom--lg">
{plugins.otherPlugins.map(pluginData => (
<PluginCard key={pluginData.title} {...pluginData}></PluginCard>
))}
</div>
</div>
</Layout>
);
</Layout>
);
};
export default Plugins;
@@ -28,10 +28,60 @@
:global(.pluginsContainer) {
gap: 1rem;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(250px, 300px));
}
@media (max-width: 768px) {
:global(.pluginsContainer) {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
}
}
:global(.hidePluginsHeader) {
display: none;
}
:global(.fit-content) {
width: fit-content;
}
:global(.pluginsFilterBox) {
width: 100%;
margin-bottom: 1rem;
height: 1rem;
}
:global(.dropdown) {
float: right;
margin-bottom: 1rem;
}
:global(.button--info) {
background-color: transparent;
border-color: var(--ifm-color-primary);
color: var(--ifm-color-primary);
min-width: 250px;
}
:global(label.dropdown__item) {
display: flex;
align-items: center;
cursor: pointer;
margin-top: 5px;
&:hover {
background-color: var(--ifm-color-primary);
color: black;
}
}
:global(.dropdown__label) {
font-size: 15px;
cursor: pointer;
}
:global(.dropdown__checkbox) {
margin-right: 10px;
cursor: pointer;
}
}
+4
View File
@@ -0,0 +1,4 @@
export type ChipCategory = {
name: string;
isSelected: boolean;
};