Skip to content

Commit

Permalink
improve search/filter components on stacks and k8s dashboard (#1175)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsladerman committed Jul 19, 2024
1 parent 420cd31 commit 479e309
Show file tree
Hide file tree
Showing 24 changed files with 732 additions and 146 deletions.
4 changes: 2 additions & 2 deletions assets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
"@nivo/pie": "0.83.0",
"@nivo/radial-bar": "0.83.0",
"@nivo/tooltip": "0.83.0",
"@pluralsh/design-system": "3.55.0",
"@pluralsh/design-system": "3.57",
"@react-hooks-library/core": "0.6.0",
"@tanstack/react-virtual": "3.0.1",
"anser": "2.1.1",
Expand Down Expand Up @@ -192,4 +192,4 @@
"lint-staged": {
"./src/**/*.{js,jsx,ts,tsx,graphql,md}": "prettier --write"
}
}
}
1 change: 1 addition & 0 deletions assets/src/components/cd/cluster/ClusterSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ function ClusterSettingsModalInner({
<Modal
asForm
portal
size="large"
open={open}
onClose={onClose}
header={props.header || `Cluster settings – ${cluster.name}`}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
Accordion,
AccordionOLD as Accordion,
AppIcon,
Button,
ChecklistIcon,
Expand Down
6 changes: 2 additions & 4 deletions assets/src/components/cd/clusters/Clusters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ import {
ClustersFilters,
} from '../services/ClustersFilters'

import { ClusterTagsFilter } from '../services/ClusterTagsFilter'
import { TagsFilter } from '../services/ClusterTagsFilter'

import { useFetchPaginatedData } from '../utils/useFetchPaginatedData'

Expand Down Expand Up @@ -225,9 +225,7 @@ export default function Clusters() {
setSelectedTagKeys={setSelectedTagKeys}
tagOp={tagOp}
setTagOp={
setTagOp as ComponentProps<
typeof ClusterTagsFilter
>['setSearchOp']
setTagOp as ComponentProps<typeof TagsFilter>['setSearchOp']
}
/>
<TabPanel
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
useState,
} from 'react'
import {
Accordion,
AccordionOLD as Accordion,
FormField,
IconFrame,
Input,
Expand Down
50 changes: 40 additions & 10 deletions assets/src/components/cd/services/ClusterTagsFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
import { type ComponentProps, type Key, useMemo, useState } from 'react'
import { TagMultiSelect } from '@pluralsh/design-system'
import uniqWith from 'lodash/uniqWith'
import isEqual from 'lodash/isEqual'
import { Conjunction, useTagPairsQuery } from 'generated/graphql'
import {
ListBoxFooterPlus,
ReloadIcon,
TagMultiSelect,
} from '@pluralsh/design-system'
import { useThrottle } from 'components/hooks/useThrottle'
import { Conjunction, TagType, useTagPairsQuery } from 'generated/graphql'
import isEqual from 'lodash/isEqual'
import uniqWith from 'lodash/uniqWith'
import { type ComponentProps, type Key, useMemo, useState } from 'react'
import { tagToKey } from 'utils/clusterTags'

export function ClusterTagsFilter({
export function TagsFilter({
type,
innerChips,
selectedTagKeys,
setSelectedTagKeys,
searchOp,
setSearchOp,
comboBoxProps,
selectProps,
}: {
type?: TagType
innerChips?: boolean
selectedTagKeys: Set<Key>
setSelectedTagKeys: (keys: Set<Key>) => void
searchOp: Conjunction
setSearchOp: ComponentProps<typeof TagMultiSelect>['onChangeMatchType']
comboBoxProps?: ComponentProps<typeof TagMultiSelect>['comboBoxProps']
selectProps?: ComponentProps<typeof TagMultiSelect>['selectProps']
}) {
const [inputValue, setInputValue] = useState('')
const throttledInputValue = useThrottle(inputValue, 100)
const throttledInputValue = useThrottle(inputValue, 150)

const {
data: currentData,
previousData,
loading,
} = useTagPairsQuery({
variables: { q: throttledInputValue },
variables: { q: throttledInputValue, type },
})
const data = currentData || previousData
const searchResults = useMemo(
Expand All @@ -47,8 +59,26 @@ export function ClusterTagsFilter({

return (
<TagMultiSelect
onSelectedTagsChange={setSelectedTagKeys}
onFilterChange={setInputValue}
innerChips={innerChips}
comboBoxProps={{
dropdownFooterFixed: (
<ListBoxFooterPlus
leftContent={<ReloadIcon />}
onClick={() => {
setSelectedTagKeys(new Set())
setInputValue('')
}}
>
Reset tags
</ListBoxFooterPlus>
),
...comboBoxProps,
}}
selectProps={selectProps}
selectedTagKeys={selectedTagKeys}
setSelectedTagKeys={setSelectedTagKeys}
inputValue={inputValue}
setInputValue={setInputValue}
loading={loading}
options={searchResults}
selectedMatchType={searchOp}
Expand Down
14 changes: 6 additions & 8 deletions assets/src/components/cd/services/ClustersFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import isNil from 'lodash/isNil'
import { useDebounce } from '@react-hooks-library/core'

import { serviceStatusToSeverity } from './ServiceStatusChip'
import { ClusterTagsFilter } from './ClusterTagsFilter'
import { TagsFilter } from './ClusterTagsFilter'

export type ClusterStatusTabKey = 'HEALTHY' | 'UNHEALTHY' | 'ALL'
export const statusTabs = Object.entries({
Expand Down Expand Up @@ -51,12 +51,10 @@ export function ClustersFilters({
setQueryString: (string) => void
tabStateRef: MutableRefObject<any>
statusCounts: Record<ClusterStatusTabKey, number | undefined>
selectedTagKeys: ComponentProps<typeof ClusterTagsFilter>['selectedTagKeys']
setSelectedTagKeys: ComponentProps<
typeof ClusterTagsFilter
>['setSelectedTagKeys']
tagOp: ComponentProps<typeof ClusterTagsFilter>['searchOp']
setTagOp: ComponentProps<typeof ClusterTagsFilter>['setSearchOp']
selectedTagKeys: ComponentProps<typeof TagsFilter>['selectedTagKeys']
setSelectedTagKeys: ComponentProps<typeof TagsFilter>['setSelectedTagKeys']
tagOp: ComponentProps<typeof TagsFilter>['searchOp']
setTagOp: ComponentProps<typeof TagsFilter>['setSearchOp']
}) {
const [searchString, setSearchString] = useState('')
const debouncedSearchString = useDebounce(searchString, 400)
Expand All @@ -74,7 +72,7 @@ export function ClustersFilters({
return (
<ClustersFiltersSC>
<div css={{ flex: '1 1 50%' }}>
<ClusterTagsFilter
<TagsFilter
selectedTagKeys={selectedTagKeys}
setSelectedTagKeys={setSelectedTagKeys}
searchOp={tagOp}
Expand Down
2 changes: 1 addition & 1 deletion assets/src/components/cluster/pods/Pods.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export const NamespaceListFooter = forwardRef<
Omit<ComponentProps<typeof ListBoxFooterPlusInner>, 'children'>
>(({ leftContent, ...props }, ref) => {
const theme = useTheme()
const label = 'View all'
const label = 'Clear selection'

return (
<ListBoxFooterPlusInner
Expand Down
10 changes: 8 additions & 2 deletions assets/src/components/kubernetes/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,14 @@ export default function Navigation() {
overflow: 'hidden',
}}
>
<div css={{ display: 'flex', gap: theme.spacing.small }}>
{headerContent}
<div
css={{
display: 'flex',
justifyContent: 'space-between',
gap: theme.spacing.small,
}}
>
<div css={{ flex: 1, overflow: 'hidden' }}>{headerContent}</div>
<DataSelectInputs dataSelect={dataSelect} />
</div>
<PageHeaderContext.Provider value={pageHeaderContext}>
Expand Down
49 changes: 36 additions & 13 deletions assets/src/components/kubernetes/common/DataSelect.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import React, {
import {
Dispatch,
SetStateAction,
createContext,
useContext,
useEffect,
useMemo,
useState,
} from 'react'

import { useTheme } from 'styled-components'

import { FiltersIcon, SearchIcon } from '@pluralsh/design-system'

import { ExpandedInput, IconExpander } from 'components/utils/IconExpander'

import { useDebounce } from 'usehooks-ts'

import { useNamespaces } from '../Cluster'

import { NameFilter } from './NameFilter'
import { NamespaceFilter } from './NamespaceFilter'

export type DataSelectT = {
Expand Down Expand Up @@ -67,27 +73,44 @@ export function DataSelectInputs({
}) {
const theme = useTheme()
const namespaces = useNamespaces()
const { namespaced, namespace, setNamespace, filter, setFilter } = dataSelect
const {
namespaced,
namespace,
setNamespace,
filter: contextFilter,
setFilter: setContextFilter,
} = dataSelect

const [filter, setFilter] = useState(contextFilter)
const debouncedFilter = useDebounce(filter, 200)

useEffect(
() => setContextFilter(debouncedFilter),
[debouncedFilter, setContextFilter]
)

return (
<div
css={{
display: 'flex',
flexGrow: 1,
gap: theme.spacing.medium,
justifyContent: 'flex-end',
}}
>
<NameFilter
value={filter}
onChange={setFilter}
/>
{namespaced && (
<NamespaceFilter
namespaces={namespaces}
namespace={namespace}
onChange={setNamespace}
<IconExpander icon={<SearchIcon />}>
<ExpandedInput
inputValue={filter}
onChange={setFilter}
/>
</IconExpander>
{namespaced && (
<IconExpander icon={<FiltersIcon />}>
<NamespaceFilter
namespaces={namespaces}
namespace={namespace}
onChange={setNamespace}
/>
</IconExpander>
)}
</div>
)
Expand Down
21 changes: 0 additions & 21 deletions assets/src/components/kubernetes/common/NameFilter.tsx

This file was deleted.

13 changes: 12 additions & 1 deletion assets/src/components/kubernetes/common/NamespaceFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { useEffect, useMemo, useState } from 'react'
import Fuse from 'fuse.js'
import { ComboBox, ListBoxItem } from '@pluralsh/design-system'

import { useTheme } from 'styled-components'

import { NamespaceListFooter } from '../../cluster/pods/Pods'

export function NamespaceFilter({
Expand All @@ -13,6 +15,7 @@ export function NamespaceFilter({
namespace: string
onChange: (arg: any) => any
}) {
const theme = useTheme()
const [value, setValue] = useState('')

useEffect(() => setValue(namespace), [namespace])
Expand All @@ -25,7 +28,15 @@ export function NamespaceFilter({

return (
<ComboBox
inputProps={{ placeholder: 'Filter by namespace' }}
startIcon={null}
showArrow={false}
inputProps={{
placeholder: 'Filter by namespace',
style: {
border: 'none',
background: theme.colors['fill-two'],
},
}}
inputValue={value}
onInputChange={setValue}
selectedKey={namespace}
Expand Down
24 changes: 8 additions & 16 deletions assets/src/components/kubernetes/common/ResourceDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { LinkTabWrap } from '../../utils/Tabs'
import { ResponsivePageFullWidth } from '../../utils/layout/ResponsivePageFullWidth'
import { ResponsiveLayoutSpacer } from '../../utils/layout/ResponsiveLayoutSpacer'
import { ResponsiveLayoutSidecarContainer } from '../../utils/layout/ResponsiveLayoutSidecarContainer'
import { ResponsiveLayoutHeader } from '../../utils/layout/ResponsiveLayoutHeader'
import { PageHeaderContext } from '../../cd/ContinuousDeployment'

export interface TabEntry {
Expand Down Expand Up @@ -53,20 +52,16 @@ export default function ResourceDetails({
},
}}
>
<ResponsiveLayoutHeader
<header
css={{
paddingRight: theme.spacing.large,
overflow: 'hidden',
display: 'flex',
justifyContent: 'space-between',
gap: theme.spacing.small,
marginBottom: theme.spacing.medium,
paddingRight: theme.spacing.xlarge,
}}
>
<div
css={{
display: 'flex',
flexGrow: 1,
maxWidth: theme.breakpoints.desktopLarge,
height: 'fit-content',
}}
>
<div css={{ flex: 1, overflow: 'hidden' }}>
<TabList
scrollable
gap="xxsmall"
Expand All @@ -75,9 +70,6 @@ export default function ResourceDetails({
orientation: 'horizontal',
selectedKey: currentTab?.path,
}}
marginRight="medium"
paddingTop="xsmall"
paddingBottom="xxsmall"
>
{tabs.map(({ label, path }) => (
<LinkTabWrap
Expand All @@ -98,7 +90,7 @@ export default function ResourceDetails({
</div>
{headerContent}
{additionalHeaderContent}
</ResponsiveLayoutHeader>
</header>
<ResponsivePageFullWidth
noPadding
maxContentWidth={theme.breakpoints.desktopLarge}
Expand Down
Loading

0 comments on commit 479e309

Please sign in to comment.