@ -10,73 +10,55 @@ import {
StatesSuggestionListItem ,
StatesSuggestionText ,
StatesTitle ,
Pagination ,
Icon ,
} from '@rocket.chat/fuselage' ;
import { useDebouncedState } from '@rocket.chat/fuselage-hooks' ;
import { useRoute , useTranslation } from '@rocket.chat/ui-contexts' ;
import React , { FC , useMemo , useState } from 'react' ;
import FilterByText from '../../../components/FilterByText' ;
import {
GenericTable ,
GenericTableBody ,
GenericTableHeader ,
GenericTableHeaderCell ,
GenericTableLoadingTable ,
} from '../../../components/GenericTable' ;
import { usePagination } from '../../../components/GenericTable/hooks/usePagination' ;
import { useResizeInlineBreakpoint } from '../../../hooks/useResizeInlineBreakpoint' ;
import { AsyncStatePhase } from '../../../lib/asyncState' ;
import AppRow from './AppRow' ;
import { useAppsReload , useAppsResult } from './AppsContext' ;
import MarketplaceRow from './MarketplaceRow' ;
import CategoryDropDown from './components/CategoryFilter/CategoryDropDown' ;
import TagList from './components/CategoryFilter/TagList' ;
import RadioDropDown from './components/RadioDropDown/RadioDropDown' ;
import AppsFilters from './AppsFilters' ;
import AppsListMain from './AppsListMain' ;
import { RadioDropDownGroup } from './definitions/RadioDropDownDefinitions' ;
import { useCategories } from './hooks/useCategories' ;
import { useFilteredApps } from './hooks/useFilteredApps' ;
import { useRadioToggle } from './hooks/useRadioToggle' ;
const AppsTable : FC < {
const AppsList : FC < {
isMarketplace : boolean ;
} > = ( { isMarketplace } ) = > {
const t = useTranslation ( ) ;
const [ ref , onLargeBreakpoint , onMediumBreakpoint ] = useResizeInlineBreakpoint ( [ 800 , 600 ] , 200 ) as [
React . RefObject < HTMLElement > ,
boolean ,
boolean ,
] ;
const { marketplaceApps , installedApps } = useAppsResult ( ) ;
const marketplaceRoute = useRoute ( 'admin-marketplace' ) ;
const Row = isMarketplace ? MarketplaceRow : AppRow ;
const [ text , setText ] = useDebouncedState ( '' , 500 ) ;
const reload = useAppsReload ( ) ;
const { current , itemsPerPage , setItemsPerPage : onSetItemsPerPage , setCurrent : onSetCurrent , . . . paginationProps } = usePagination ( ) ;
const [ freePaidFilterStructure , setFreePaidFilterStructure ] = useState < RadioDropDownGroup > ( {
const marketplaceRoute = useRoute ( 'admin-marketplace' ) ;
const [ freePaidFilterStructure , setFreePaidFilterStructure ] = useState ( {
label : t ( 'Filter_By_Price' ) ,
items : [
{ id : 'all' , label : t ( 'All_App s' ) , checked : true } ,
{ id : 'all' , label : t ( 'All_Price s' ) , checked : true } ,
{ id : 'free' , label : t ( 'Free_Apps' ) , checked : false } ,
{ id : 'paid' , label : t ( 'Paid_Apps' ) , checked : false } ,
] ,
} ) ;
const freePaidFilterOnSelected = useRadioToggle ( setFreePaidFilterStructure ) ;
const [ categories , selectedCategories , categoryTagList , onSelected ] = useCategories ( ) ;
const [ statusFilterStructure , setStatusFilterStructure ] = useState ( {
label : t ( 'Filter_By_Status' ) ,
items : [
{ id : 'all' , label : t ( 'All_status' ) , checked : true } ,
{ id : 'enabled' , label : t ( 'Enabled' ) , checked : false } ,
{ id : 'disabled' , label : t ( 'Disabled' ) , checked : false } ,
] ,
} ) ;
const statusFilterOnSelected = useRadioToggle ( setStatusFilterStructure ) ;
const [ sortFilterStructure , setSortFilterStructure ] = useState < RadioDropDownGroup > ( {
label : 'Sort by' ,
label : t ( 'Sort_By' ) ,
items : [
{ id : 'az' , label : 'A-Z' , checked : true } ,
{ id : 'za' , label : 'Z-A' , checked : false } ,
@ -84,9 +66,9 @@ const AppsTable: FC<{
{ id : 'lru' , label : t ( 'Least_recent_updated' ) , checked : false } ,
] ,
} ) ;
const sortFilterOnSelected = useRadioToggle ( setSortFilterStructure ) ;
const [ categories , selectedCategories , categoryTagList , onSelected ] = useCategories ( ) ;
const appsResult = useFilteredApps ( {
appsData : isMarketplace ? marketplaceApps : installedApps ,
text ,
@ -95,57 +77,53 @@ const AppsTable: FC<{
categories : useMemo ( ( ) = > selectedCategories . map ( ( { label } ) = > label ) , [ selectedCategories ] ) ,
purchaseType : useMemo ( ( ) = > freePaidFilterStructure . items . find ( ( { checked } ) = > checked ) ? . id , [ freePaidFilterStructure ] ) ,
sortingMethod : useMemo ( ( ) = > sortFilterStructure . items . find ( ( { checked } ) = > checked ) ? . id , [ sortFilterStructure ] ) ,
status : useMemo ( ( ) = > statusFilterStructure . items . find ( ( { checked } ) = > checked ) ? . id , [ statusFilterStructure ] ) ,
} ) ;
const isAppListReadyOrLoading =
appsResult . phase === AsyncStatePhase . LOADING || ( appsResult . phase === AsyncStatePhase . RESOLVED && Boolean ( appsResult . value . count ) ) ;
const noInstalledAppsFound = appsResult . phase === AsyncStatePhase . RESOLVED && ! isMarketplace && appsResult . value . total === 0 ;
const noMarketplaceOrInstalledAppMatches = appsResult . phase === AsyncStatePhase . RESOLVED && isMarketplace && appsResult . value . count === 0 ;
const noInstalledAppMatches =
appsResult . phase === AsyncStatePhase . RESOLVED && ! isMarketplace && appsResult . value . total !== 0 && appsResult . value . count === 0 ;
return (
< >
{ /* TODO Divide into two components: Filters and AppsTable */ }
< FilterByText placeholder = { t ( 'Search_Apps' ) } onChange = { ( { text } ) : void = > setText ( text ) } >
< RadioDropDown group = { freePaidFilterStructure } onSelected = { freePaidFilterOnSelected } mie = 'x8' / >
< CategoryDropDown data = { categories } selectedCategories = { selectedCategories } onSelected = { onSelected } / >
< RadioDropDown group = { sortFilterStructure } onSelected = { sortFilterOnSelected } mis = 'x8' / >
< / FilterByText >
< TagList categories = { categoryTagList } onClick = { onSelected } / >
{ ( appsResult . phase === AsyncStatePhase . LOADING ||
( appsResult . phase === AsyncStatePhase . RESOLVED && Boolean ( appsResult . value . count ) ) ) && (
< >
< GenericTable ref = { ref } >
< GenericTableHeader >
< GenericTableHeaderCell width = { onMediumBreakpoint ? 'x240' : 'x180' } > { t ( 'Name' ) } < / GenericTableHeaderCell >
{ onMediumBreakpoint && < GenericTableHeaderCell > { t ( 'Details' ) } < / GenericTableHeaderCell > }
{ isMarketplace && < GenericTableHeaderCell > { t ( 'Price' ) } < / GenericTableHeaderCell > }
< GenericTableHeaderCell width = 'x160' > { t ( 'Status' ) } < / GenericTableHeaderCell >
< / GenericTableHeader >
< GenericTableBody >
{ appsResult . phase === AsyncStatePhase . LOADING && (
< GenericTableLoadingTable
// eslint-disable-next-line no-nested-ternary
headerCells = { onMediumBreakpoint ? ( isMarketplace ? 4 : 3 ) : 2 }
/ >
) }
{ appsResult . phase === AsyncStatePhase . RESOLVED &&
appsResult . value . items . map ( ( app ) = > < Row key = { app . id } large = { onLargeBreakpoint } medium = { onMediumBreakpoint } { ...app } / > ) }
< / GenericTableBody >
< / GenericTable >
{ appsResult . phase === AsyncStatePhase . RESOLVED && (
< Pagination
current = { current }
itemsPerPage = { itemsPerPage }
count = { appsResult . value . total }
onSetItemsPerPage = { onSetItemsPerPage }
onSetCurrent = { onSetCurrent }
{ . . . paginationProps }
/ >
) }
< / >
< AppsFilters
setText = { setText }
freePaidFilterStructure = { freePaidFilterStructure }
freePaidFilterOnSelected = { freePaidFilterOnSelected }
categories = { categories }
selectedCategories = { selectedCategories }
onSelected = { onSelected }
sortFilterStructure = { sortFilterStructure }
sortFilterOnSelected = { sortFilterOnSelected }
categoryTagList = { categoryTagList }
statusFilterStructure = { statusFilterStructure }
statusFilterOnSelected = { statusFilterOnSelected }
/ >
{ isAppListReadyOrLoading && (
< AppsListMain
appsResult = { appsResult }
current = { current }
itemsPerPage = { itemsPerPage }
onSetItemsPerPage = { onSetItemsPerPage }
onSetCurrent = { onSetCurrent }
paginationProps = { paginationProps }
isMarketplace = { isMarketplace }
/ >
) }
{ appsResult . phase === AsyncStatePhase . RESOLVED && isMarketplace && appsResult . value . count === 0 && (
{ noMarketplaceOrInstalledAppMatches && (
< Box mbs = 'x20' >
< States >
< StatesIcon name = 'magnifier' / >
< StatesTitle > { t ( 'No_app_matches' ) } < / StatesTitle >
{ appsResult . value . shouldShowSearchText ? (
{ appsResult ? . value ? . shouldShowSearchText ? (
< StatesSubtitle >
{ t ( 'No_marketplace_matches_for' ) } : < strong > "{text}" < / strong >
< / StatesSubtitle >
@ -164,24 +142,13 @@ const AppsTable: FC<{
< / States >
< / Box >
) }
{ appsResult . phase === AsyncStatePhase . RESOLVED && ! isMarketplace && appsResult . value . total === 0 && (
< Box mbs = 'x20' >
< States >
< StatesIcon name = 'magnifier' / >
< StatesTitle > { t ( 'No_apps_installed' ) } < / StatesTitle >
< StatesSubtitle > { t ( 'Explore_the_marketplace_to_find_awesome_apps' ) } < / StatesSubtitle >
< StatesActions >
< StatesAction onClick = { ( ) : void = > marketplaceRoute . push ( { context : '' } ) } > { t ( 'Explore_marketplace' ) } < / StatesAction >
< / StatesActions >
< / States >
< / Box >
) }
{ appsResult . phase === AsyncStatePhase . RESOLVED && ! isMarketplace && appsResult . value . total !== 0 && appsResult . value . count === 0 && (
{ noInstalledAppMatches && (
< Box mbs = 'x20' >
< States >
< StatesIcon name = 'magnifier' / >
< StatesTitle > { t ( 'No_installed_app_matches' ) } < / StatesTitle >
{ appsResult . value . shouldShowSearchText ? (
{ appsResult ? . value ? . shouldShowSearchText ? (
< StatesSubtitle >
< span >
{ t ( 'No_app_matches_for' ) } < strong > "{text}" < / strong >
@ -199,6 +166,20 @@ const AppsTable: FC<{
< / States >
< / Box >
) }
{ noInstalledAppsFound && (
< Box mbs = 'x20' >
< States >
< StatesIcon name = 'magnifier' / >
< StatesTitle > { t ( 'No_apps_installed' ) } < / StatesTitle >
< StatesSubtitle > { t ( 'Explore_the_marketplace_to_find_awesome_apps' ) } < / StatesSubtitle >
< StatesActions >
< StatesAction onClick = { ( ) : void = > marketplaceRoute . push ( { context : '' } ) } > { t ( 'Explore_marketplace' ) } < / StatesAction >
< / StatesActions >
< / States >
< / Box >
) }
{ appsResult . phase === AsyncStatePhase . REJECTED && (
< Box mbs = 'x20' >
< States >
@ -218,4 +199,4 @@ const AppsTable: FC<{
) ;
} ;
export default AppsTable ;
export default AppsList ;