feat: filter form for table
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
import OverlayScroller from '@/components/overlay-scroller';
|
import OverlayScroller from '@/components/overlay-scroller';
|
||||||
import { FilterOutlined } from '@ant-design/icons';
|
import { CloseCircleFilled, FilterOutlined } from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Button, Form, Popover } from 'antd';
|
import { Badge, Button, Form, Popover } from 'antd';
|
||||||
import React, { useState } from 'react';
|
import React, { useState } from 'react';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
@@ -26,6 +26,36 @@ const Container = styled.div`
|
|||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const ButtonWrapper = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: relative;
|
||||||
|
.badge {
|
||||||
|
position: absolute;
|
||||||
|
top: 4px;
|
||||||
|
right: 4px;
|
||||||
|
}
|
||||||
|
.close-btn {
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
top: -4px;
|
||||||
|
right: -4px;
|
||||||
|
font-size: 12px;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: var(--ant-color-text-quaternary);
|
||||||
|
background-color: var(--ant-color-bg-container);
|
||||||
|
&:hover {
|
||||||
|
color: var(--ant-color-text-tertiary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
.close-btn {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
const FilterForm: React.FC<
|
const FilterForm: React.FC<
|
||||||
React.PropsWithChildren & {
|
React.PropsWithChildren & {
|
||||||
width?: number;
|
width?: number;
|
||||||
@@ -40,12 +70,12 @@ const FilterForm: React.FC<
|
|||||||
width = 300,
|
width = 300,
|
||||||
contentHeight = 400,
|
contentHeight = 400,
|
||||||
initialValues = {},
|
initialValues = {},
|
||||||
hasFilters = false,
|
|
||||||
onClose,
|
onClose,
|
||||||
onValuesChange
|
onValuesChange
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
|
const [hasFilters, setHasFilters] = useState(false);
|
||||||
const [form] = Form.useForm();
|
const [form] = Form.useForm();
|
||||||
|
|
||||||
const handleToggle = () => {
|
const handleToggle = () => {
|
||||||
@@ -60,6 +90,7 @@ const FilterForm: React.FC<
|
|||||||
form.resetFields(Object.keys(initialValues));
|
form.resetFields(Object.keys(initialValues));
|
||||||
onValuesChange?.({}, initialValues);
|
onValuesChange?.({}, initialValues);
|
||||||
setOpen(false);
|
setOpen(false);
|
||||||
|
setHasFilters(false);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleOnClose = () => {
|
const handleOnClose = () => {
|
||||||
@@ -67,6 +98,14 @@ const FilterForm: React.FC<
|
|||||||
onClose?.();
|
onClose?.();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleOnValuesChange = (changedValues: any, allValues: any) => {
|
||||||
|
onValuesChange?.(changedValues, allValues);
|
||||||
|
const hasActiveFilters = Object.values(allValues).some(
|
||||||
|
(value) => value !== undefined && value !== null && value !== ''
|
||||||
|
);
|
||||||
|
setHasFilters(hasActiveFilters);
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Popover
|
<Popover
|
||||||
open={open}
|
open={open}
|
||||||
@@ -84,7 +123,7 @@ const FilterForm: React.FC<
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Form
|
<Form
|
||||||
onValuesChange={onValuesChange}
|
onValuesChange={handleOnValuesChange}
|
||||||
initialValues={initialValues}
|
initialValues={initialValues}
|
||||||
form={form}
|
form={form}
|
||||||
>
|
>
|
||||||
@@ -113,7 +152,27 @@ const FilterForm: React.FC<
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button onClick={handleToggle} icon={<FilterOutlined />}></Button>
|
<ButtonWrapper>
|
||||||
|
<Button icon={<FilterOutlined />} onClick={handleToggle}></Button>
|
||||||
|
{hasFilters && (
|
||||||
|
<Badge
|
||||||
|
dot
|
||||||
|
color={'var(--ant-color-primary-text-hover)'}
|
||||||
|
className="badge"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{hasFilters && (
|
||||||
|
<span className="close-btn">
|
||||||
|
<CloseCircleFilled
|
||||||
|
style={{ fontSize: 12 }}
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
handleOnReset();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
</ButtonWrapper>
|
||||||
</Popover>
|
</Popover>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ import {
|
|||||||
ModelInstanceListItem,
|
ModelInstanceListItem,
|
||||||
SourceType
|
SourceType
|
||||||
} from '../config/types';
|
} from '../config/types';
|
||||||
|
import Filters from '../filters';
|
||||||
import useEditDeployment from '../hooks/use-edit-deployment';
|
import useEditDeployment from '../hooks/use-edit-deployment';
|
||||||
import useFilterStatus from '../hooks/use-filter-status';
|
import useFilterStatus from '../hooks/use-filter-status';
|
||||||
import useFormInitialValues from '../hooks/use-form-initial-values';
|
import useFormInitialValues from '../hooks/use-form-initial-values';
|
||||||
@@ -649,7 +650,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
options={statusOptions}
|
options={statusOptions}
|
||||||
onChange={handleStatusChange}
|
onChange={handleStatusChange}
|
||||||
></BaseSelect>
|
></BaseSelect>
|
||||||
{/* <Filters
|
<Filters
|
||||||
initialValues={{
|
initialValues={{
|
||||||
cluster_id: undefined,
|
cluster_id: undefined,
|
||||||
state: undefined,
|
state: undefined,
|
||||||
@@ -657,7 +658,7 @@ const Models: React.FC<ModelsProps> = ({
|
|||||||
}}
|
}}
|
||||||
clusterList={clusterList}
|
clusterList={clusterList}
|
||||||
onValuesChange={onFilterChange}
|
onValuesChange={onFilterChange}
|
||||||
></Filters> */}
|
></Filters>
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
style={{ color: 'var(--ant-color-text-tertiary)' }}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import BaseSelect from '@/components/seal-form/base/select';
|
|||||||
import FilterForm from '@/pages/_components/filter-form';
|
import FilterForm from '@/pages/_components/filter-form';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Form } from 'antd';
|
import { Form } from 'antd';
|
||||||
import _ from 'lodash';
|
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { modelCategories } from '../config';
|
import { modelCategories } from '../config';
|
||||||
import useFilterStatus from '../hooks/use-filter-status';
|
import useFilterStatus from '../hooks/use-filter-status';
|
||||||
@@ -25,12 +24,10 @@ const FilterFormContent: React.FC<FilterFormContentProps> = ({
|
|||||||
onValuesChange
|
onValuesChange
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
const form = Form.useFormInstance();
|
|
||||||
const { labelRender, optionRender, statusOptions } = useFilterStatus();
|
const { labelRender, optionRender, statusOptions } = useFilterStatus();
|
||||||
|
|
||||||
const handleOnValuesChange = (changedValues: any, allValues: any) => {
|
const handleOnValuesChange = (changedValues: any, allValues: any) => {
|
||||||
const query = _.pickBy(allValues, (value: any) => !!value);
|
onValuesChange?.(allValues);
|
||||||
onValuesChange?.(query);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
Reference in New Issue
Block a user