1- import { Heading , HStack , Stack , Tag , Text , VStack , Wrap , WrapItem } from '@chakra-ui/react' ;
1+ import { FormControl , FormLabel , Heading , HStack , Select , Stack , Tag , Text , VStack , Wrap , WrapItem } from '@chakra-ui/react' ;
22import { Link , useLoaderData , useLocation } from '@remix-run/react' ;
33import type { LoaderFunction , MetaFunction } from '@remix-run/server-runtime' ;
44import { json } from '@remix-run/server-runtime' ;
55import { parseNamespacedId , WorkflowType } from '@runnablejs/api' ;
6+ import { useState } from 'react' ;
67import { Iconify } from '../components/icons/Iconify' ;
78import { Page } from '../components/layout/Page' ;
89import { getUrl } from '../utils/routes' ;
910import { groupBy } from '../utils/objects' ;
11+ import { uniq } from '../utils/array' ;
1012
1113type LoaderData = {
1214 actions : WorkflowType [ ] ;
@@ -23,19 +25,46 @@ export const meta: MetaFunction<LoaderData> = () => {
2325 } ;
2426} ;
2527
28+ const defaultNamespace = 'All' ;
29+
2630export default function ActionsIndexPage ( ) {
2731 const { actions } = useLoaderData < LoaderData > ( ) ;
2832
29- const categories = groupBy ( actions , ( action ) => action . category || 'Other' ) ;
30- // sort, but 'Other' comes last
33+ // Namespace filter
34+ const [ selectedNamespace , setSelectedNamespace ] = useState < string > ( defaultNamespace ) ;
35+ const namespaces = uniq ( actions . map ( ( action ) => parseNamespacedId ( action . id ) [ 0 ] ) . filter ( Boolean ) ) . sort ( ) ;
36+
37+ // Filter actions by namespace
38+ const filteredActions = selectedNamespace === defaultNamespace ? actions : actions . filter ( ( action ) => parseNamespacedId ( action . id ) [ 0 ] === selectedNamespace ) ;
39+
40+ // Categorize actions
41+ const categories = groupBy ( filteredActions , ( action ) => action . category ) ;
3142 const sortedCategories = Object . entries ( categories ) . sort ( ( [ a ] , [ b ] ) => {
32- if ( a === 'Other' ) return 1 ;
33- if ( b === 'Other' ) return - 1 ;
3443 return a . localeCompare ( b ) ;
3544 } ) ;
3645
46+
3747 return (
3848 < Page title = "Actions" animationKey = { useLocation ( ) . pathname } >
49+ < FormControl width = { 350 } mb = { 10 } >
50+ < FormLabel > Namespace</ FormLabel >
51+ < Select
52+ size = 'md'
53+ bg = 'white'
54+ value = { selectedNamespace }
55+ onChange = { ( evt ) => {
56+ setSelectedNamespace ( evt . target . value )
57+ } }
58+ >
59+ < option value = { defaultNamespace } > All</ option >
60+ { namespaces . map ( ( ns ) => (
61+ < option key = { ns } value = { ns } >
62+ { ns }
63+ </ option >
64+ ) ) }
65+ </ Select >
66+ </ FormControl >
67+
3968 < Stack direction = "column" spacing = { 10 } >
4069 { sortedCategories . map ( ( [ category , actionGroup ] ) => (
4170 < Stack key = { category } direction = "column" >
0 commit comments