feat(pluginsFilter): added dropdown filter for plugins list

Signed-off-by: antonio.bergas <anthonyprincedom@hotmail.com>
This commit is contained in:
antonio.bergas
2023-04-28 14:51:57 +02:00
parent 26d952fc6e
commit 6cd4177c64
4 changed files with 202 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}>
<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;
+128 -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,135 @@ 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 allCategories: ChipCategory[] = [];
plugins.corePlugins.concat(plugins.otherPlugins).forEach(pluginData => {
const index = allCategories.findIndex(
chip => chip.name === pluginData.category,
);
if (index === -1) {
allCategories.push({
name: pluginData.category,
isSelected: false,
});
}
});
<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 [categories, setCategories] = useState(allCategories);
const [selectedCategories, setSelectedCategories] = useState([]);
const [showCoreFeaturesHeader, setShowCoreFeaturesHeader] = useState(true);
const [showOtherPluginsHeader, setShowOtherPluginsHeader] = useState(true);
const handleChipClick = (categoryName: string) => {
console.log(categoryName);
const category = categories.find(
category => category.name === categoryName,
);
const isSelected = category?.isSelected || false;
let newSelectedCategories = selectedCategories;
if (isSelected) {
newSelectedCategories = selectedCategories.filter(
c => c !== categoryName,
);
} else {
newSelectedCategories.push(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')) {
setShowCoreFeaturesHeader(false);
} else {
setShowCoreFeaturesHeader(true);
}
if (
newSelectedCategories.length === 1 &&
newSelectedCategories[0] === 'Core Feature'
) {
setShowOtherPluginsHeader(false);
} else {
setShowOtherPluginsHeader(true);
}
if (newSelectedCategories.length === 0) {
setShowOtherPluginsHeader(true);
setShowCoreFeaturesHeader(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>
<PluginsFilter
categories={categories}
handleChipClick={handleChipClick}
/>
{showCoreFeaturesHeader && <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>
{showOtherPluginsHeader && <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 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,43 @@
:global(.pluginsContainer) {
gap: 1rem;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
grid-template-columns: repeat(auto-fit, minmax(250px, 300px));
}
:global(.fit-content) {
width: fit-content;
}
:global(.dropdown) {
float: right;
}
: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;
};