diff --git a/package-lock.json b/package-lock.json
index edb6f789..af764d43 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@dassana-io/web-components",
- "version": "0.9.3",
+ "version": "0.9.4",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/package.json b/package.json
index f3911112..4b5a7411 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "@dassana-io/web-components",
- "version": "0.9.3",
+ "version": "0.9.4",
"publishConfig": {
"registry": "https://npm.pkg.github.com/dassana-io"
},
diff --git a/src/__mocks__/filter_mock_data.ts b/src/__mocks__/filter_mock_data.ts
new file mode 100644
index 00000000..639963db
--- /dev/null
+++ b/src/__mocks__/filter_mock_data.ts
@@ -0,0 +1,46 @@
+import { FilterOptions } from '../components/Filters'
+
+export const mockDynamicFilterOptions = [
+ {
+ id: '5391d028-d5fe-4c33-a4c9-8719191aaeb1',
+ name: 'Ingestion Dev Account'
+ },
+ {
+ id: '5391d028-d5fe-4c33-a4c9-8719191aaeb8',
+ name: 'Ingestion Prod Account'
+ }
+]
+
+export const mockFilterOptions: FilterOptions = [
+ {
+ filterKey: 'name',
+ options: [
+ 'Dev account',
+ 'Prod account 1',
+ 'Prod account 2',
+ 'Test account'
+ ],
+ staticFilter: false
+ },
+ {
+ filterKey: 'service',
+ options: [
+ 'EC2',
+ 'S3',
+ 'RDS',
+ 'Amazon Keyspaces (for Apache Cassandra)',
+ 'EKS'
+ ],
+ staticFilter: true
+ },
+ {
+ filterKey: 'model',
+ options: ['instance', 'bucket', 'table'],
+ staticFilter: true
+ },
+ {
+ filterKey: 'region',
+ options: ['us-west-1', 'us-east-2', 'ap-south-1'],
+ staticFilter: true
+ }
+]
diff --git a/src/__mocks__/index.ts b/src/__mocks__/index.ts
new file mode 100644
index 00000000..37e8cf61
--- /dev/null
+++ b/src/__mocks__/index.ts
@@ -0,0 +1,2 @@
+export * from './filter_mock_data'
+export * from './table_mock_data'
diff --git a/src/__snapshots__/storybook.test.ts.snap b/src/__snapshots__/storybook.test.ts.snap
index e70abd3a..472ca7e3 100644
--- a/src/__snapshots__/storybook.test.ts.snap
+++ b/src/__snapshots__/storybook.test.ts.snap
@@ -2825,6 +2825,42 @@ exports[`Storyshots Skeleton Default 1`] = `
`;
+exports[`Storyshots Tabs Default 1`] = `
+
+
+
+
+ Foo
+
+
+ Bar
+
+
+
+
+
+`;
+
exports[`Storyshots Tag Colored 1`] = `
void
+ dynamicOptions?: SelectOption[]
+ dynamicSearchVal: string
+ filtersList: FiltersList
+ onVisibleChange: (visible: boolean) => void
+ onClickAddFilter: () => void
+ onDelete: (selectedId: string) => void
+ onFilterChange: (selectedId: string, selection: string | string[]) => void
+ onSearchWrapper: OnSearchWrapper
+ pending: boolean
+ setFiltersList: React.Dispatch
>
+ visible?: boolean
+}
+
+export const FilterPopover: FC = ({
+ allFilters,
+ closePopover,
+ dynamicOptions,
+ dynamicSearchVal,
+ filtersList,
+ onVisibleChange,
+ onClickAddFilter,
+ onDelete,
+ onFilterChange,
+ onSearchWrapper,
+ pending,
+ setFiltersList,
+ visible = false
+}: FilterPopoverProps) => {
+ const classes = usePopoverStyles()
+
+ return (
+
+
+
+
+
+
+
+ {filtersList.length > 0 && (
+
setFiltersList([])}
+ >
+ Clear Filters
+
+ )}
+
+
+ {filtersList.map((filterItem, i) => (
+
+ ))}
+
+
+ }
+ onVisibleChange={onVisibleChange}
+ placement='bottomLeft'
+ popupContainerSelector='#filters-popup-wrapper'
+ popupTriggerClasses={[classes.popoverTrigger]}
+ trigger='click'
+ visible={visible}
+ >
+
+
+ )
+}
diff --git a/src/components/Filters/FilterUnit.tsx b/src/components/Filters/FilterUnit.tsx
new file mode 100644
index 00000000..e4cfd9cd
--- /dev/null
+++ b/src/components/Filters/FilterUnit.tsx
@@ -0,0 +1,135 @@
+import { faEquals } from '@fortawesome/free-solid-svg-icons'
+import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
+import { IconButton } from 'components/IconButton'
+import uniq from 'lodash/uniq'
+import {
+ FilterOption,
+ FiltersList,
+ OnSearchWrapper,
+ ProcessedFilters
+} from './types'
+import {
+ formatFilterOptions,
+ getFilterKeysOptions,
+ useFilterUnitStyles
+} from './utils'
+import { MultiSelect, Select, SelectOption } from 'components/Select'
+import React, { FC } from 'react'
+
+interface FilterUnitProps {
+ id: string
+ allFilters: ProcessedFilters
+ dynamicOptions?: SelectOption[]
+ dynamicSearchVal: string
+ onDelete: (selectedId: string) => void
+ onFilterChange: (selectedId: string, selection: string | string[]) => void
+ filtersList: FiltersList
+ onSearchWrapper: OnSearchWrapper
+ pending: boolean
+ selectedFilterKey?: string
+}
+
+const FilterUnit: FC
= ({
+ id,
+ allFilters = {},
+ dynamicOptions,
+ dynamicSearchVal,
+ filtersList = [],
+ onDelete,
+ onFilterChange,
+ onSearchWrapper,
+ pending,
+ selectedFilterKey = ''
+}: FilterUnitProps) => {
+ const classes = useFilterUnitStyles()
+
+ const renderKey = () => (
+