11import Link from '@docusaurus/Link' ;
22import Layout from '@theme/Layout' ;
33import clsx from 'clsx' ;
4- import React from 'react' ;
5-
4+ import React , { useState } from 'react' ;
65import { IPluginData , PluginCard } from './_pluginCard' ;
76import pluginsStyles from './plugins.module.scss' ;
7+ import { ChipCategory } from '@site/src/util/types' ;
88import { truncateDescription } from '@site/src/util/truncateDescription' ;
9+ import PluginsFilter from '@site/src/components/pluginsFilter/pluginsFilter' ;
910
10- //#region Plugin data import
1111const pluginsContext = require . context (
1212 '../../../data/plugins' ,
1313 false ,
@@ -29,50 +29,137 @@ const plugins = pluginsContext.keys().reduce(
2929
3030plugins . corePlugins . sort ( ( a , b ) => a . order - b . order ) ;
3131plugins . otherPlugins . sort ( ( a , b ) => a . order - b . order ) ;
32- //#endregion
33-
34- const Plugins = ( ) => (
35- < Layout >
36- < div
37- className = { clsx ( 'container' , 'padding--lg' , pluginsStyles . pluginsPage ) }
38- >
39- < div className = "marketplaceBanner" >
40- < div className = "marketplaceContent" >
41- < h2 > Plugin Marketplace</ h2 >
42-
43- < p >
44- Open source plugins that you can add to your Backstage deployment.
45- Learn how to build a < Link to = "/docs/plugins" > plugin</ Link > .
46- </ p >
47- </ div >
4832
49- < Link
50- to = "/docs/plugins/add-to-marketplace"
51- className = "button button--outline button--primary"
52- >
53- Add to Marketplace
54- </ Link >
55- </ div >
33+ const Plugins = ( ) => {
34+ const allCategoriesSet = new Set (
35+ [ ...plugins . corePlugins , ...plugins . otherPlugins ] . map (
36+ ( { category } ) => category ,
37+ ) ,
38+ ) ;
39+ const allCategoriesArray = Array . from ( allCategoriesSet ) . map ( category => ( {
40+ name : category ,
41+ isSelected : false ,
42+ } ) ) ;
43+ const [ categories , setCategories ] =
44+ useState < ChipCategory [ ] > ( allCategoriesArray ) ;
45+ const [ selectedCategories , setSelectedCategories ] = useState < string [ ] > ( [ ] ) ;
46+ const [ showCoreFeatures , setShowCoreFeatures ] = useState ( true ) ;
47+ const [ showOtherPlugins , setShowOtherPlugins ] = useState ( true ) ;
5648
57- < div className = "bulletLine margin-bottom--lg" > </ div >
49+ const handleChipClick = ( categoryName : string ) => {
50+ const isSelected =
51+ categories . find ( category => category . name === categoryName ) ?. isSelected ||
52+ false ;
5853
59- < h2 > Core Features</ h2 >
54+ const newSelectedCategories = isSelected
55+ ? selectedCategories . filter ( c => c !== categoryName )
56+ : [ ...selectedCategories , categoryName ] ;
6057
61- < div className = "pluginsContainer margin-bottom--lg" >
62- { plugins . corePlugins . map ( pluginData => (
63- < PluginCard key = { pluginData . title } { ...pluginData } > </ PluginCard >
64- ) ) }
65- </ div >
58+ setSelectedCategories ( newSelectedCategories ) ;
59+
60+ const newCategories = categories . map ( category => {
61+ if ( category . name === categoryName ) {
62+ return { ...category , isSelected : ! isSelected } ;
63+ }
64+ return category ;
65+ } ) ;
66+
67+ setCategories ( newCategories ) ;
68+
69+ if ( ! newSelectedCategories . includes ( 'Core Feature' ) ) {
70+ setShowCoreFeatures ( false ) ;
71+ } else {
72+ setShowCoreFeatures ( true ) ;
73+ }
74+
75+ if (
76+ newSelectedCategories . length === 1 &&
77+ newSelectedCategories [ 0 ] === 'Core Feature'
78+ ) {
79+ setShowOtherPlugins ( false ) ;
80+ } else {
81+ setShowOtherPlugins ( true ) ;
82+ }
6683
67- < h2 > All Plugins</ h2 >
84+ if ( newSelectedCategories . length === 0 ) {
85+ setShowOtherPlugins ( true ) ;
86+ setShowCoreFeatures ( true ) ;
87+ }
88+ } ;
6889
69- < div className = "pluginsContainer margin-bottom--lg" >
70- { plugins . otherPlugins . map ( pluginData => (
71- < PluginCard key = { pluginData . title } { ...pluginData } > </ PluginCard >
72- ) ) }
90+ return (
91+ < Layout >
92+ < div
93+ className = { clsx ( 'container' , 'padding--lg' , pluginsStyles . pluginsPage ) }
94+ >
95+ < div className = "marketplaceBanner" >
96+ < div className = "marketplaceContent" >
97+ < h2 > Plugin Marketplace</ h2 >
98+
99+ < p >
100+ Open source plugins that you can add to your Backstage deployment.
101+ Learn how to build a < Link to = "/docs/plugins" > plugin</ Link > .
102+ </ p >
103+ </ div >
104+
105+ < Link
106+ to = "/docs/plugins/add-to-marketplace"
107+ className = "button button--outline button--primary"
108+ >
109+ Add to Marketplace
110+ </ Link >
111+ </ div >
112+
113+ < div className = "bulletLine margin-bottom--lg" > </ div >
114+ < div className = "pluginsFilterBox" >
115+ < PluginsFilter
116+ categories = { categories }
117+ handleChipClick = { handleChipClick }
118+ />
119+ </ div >
120+
121+ { showCoreFeatures && (
122+ < div >
123+ < h2 > Core Features</ h2 >
124+ < div className = "pluginsContainer margin-bottom--lg" >
125+ { plugins . corePlugins
126+ . filter (
127+ pluginData =>
128+ ! selectedCategories . length ||
129+ selectedCategories . includes ( pluginData . category ) ,
130+ )
131+ . map ( pluginData => (
132+ < PluginCard
133+ key = { pluginData . title }
134+ { ...pluginData }
135+ > </ PluginCard >
136+ ) ) }
137+ </ div >
138+ </ div >
139+ ) }
140+
141+ { showOtherPlugins && (
142+ < div >
143+ < h2 > All Plugins</ h2 >
144+ < div className = "pluginsContainer margin-bottom--lg" >
145+ { plugins . otherPlugins
146+ . filter (
147+ pluginData =>
148+ ! selectedCategories . length ||
149+ selectedCategories . includes ( pluginData . category ) ,
150+ )
151+ . map ( pluginData => (
152+ < PluginCard
153+ key = { pluginData . title }
154+ { ...pluginData }
155+ > </ PluginCard >
156+ ) ) }
157+ </ div >
158+ </ div >
159+ ) }
73160 </ div >
74- </ div >
75- </ Layout >
76- ) ;
161+ </ Layout >
162+ ) ;
163+ } ;
77164
78165export default Plugins ;
0 commit comments