Files
supersonic/webapp/packages/supersonic-fe/src/components/RemoteSelect/index.tsx
tristanliu 18aa14118c [improvement][semantic-fe] Redesigning the indicator homepage to incorporate trend charts and table functionality for indicators (#347)
* [improvement][semantic-fe] Add model alias setting & Add view permission restrictions to the model permission management tab.
[improvement][semantic-fe] Add permission control to the action buttons for the main domain; apply high sensitivity filtering to the authorization of metrics/dimensions.
[improvement][semantic-fe] Optimize the editing mode in the dimension/metric/datasource components to use the modelId stored in the database for data, instead of relying on the data from the state manager.

* [improvement][semantic-fe] Add time granularity setting in the data source configuration.

* [improvement][semantic-fe] Dictionary import for dimension values supported in Q&A visibility

* [improvement][semantic-fe] Modification of data source creation prompt wording"

* [improvement][semantic-fe] metric market experience optimization

* [improvement][semantic-fe] enhance the analysis of metric trends

* [improvement][semantic-fe] optimize the presentation of metric trend permissions

* [improvement][semantic-fe] add metric trend download functionality

* [improvement][semantic-fe] fix the dimension initialization issue in metric correlation

* [improvement][semantic-fe] Fix the issue of database changes not taking effect when creating based on an SQL data source.

* [improvement][semantic-fe] Optimizing pagination logic and some CSS styles

* [improvement][semantic-fe] Fixing the API for the indicator list by changing "current" to "pageNum"

* [improvement][semantic-fe] Fixing the default value setting for the indicator list

* [improvement][semantic-fe] Adding batch operations for indicators/dimensions/models

* [improvement][semantic-fe] Replacing the single status update API for indicators/dimensions with a batch update API

* [improvement][semantic-fe] Redesigning the indicator homepage to incorporate trend charts and table functionality for indicators
2023-11-09 05:37:36 -06:00

144 lines
3.8 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import React, {
useState,
useRef,
useMemo,
useEffect,
forwardRef,
useImperativeHandle,
Ref,
} from 'react';
import { Select, Spin, Empty } from 'antd';
import debounce from 'lodash/debounce';
// import type { ValueTextType } from '@/constants';
import isFunction from 'lodash/isFunction';
type Props = {
fetchOptions: (...restParams: any[]) => Promise<{ label: any; value: any }[]>;
debounceTimeout?: number;
formatPropsValue?: (value: any) => any;
formatFetchOptionsParams?: (inputValue: string, ctx?: any) => any[];
formatOptions?: (data: any, ctx: any) => any[];
autoInit?: boolean;
disabledSearch?: boolean;
[key: string]: any;
};
type SelectOptions = {
label: string;
} & {
text: string;
} & {
value: any;
};
export type RemoteSelectImperativeHandle = {
emitSearch: (value: string) => void;
};
const { Option } = Select;
const DebounceSelect = forwardRef(
(
{
autoInit = false,
fetchOptions,
debounceTimeout = 500,
formatPropsValue,
formatFetchOptionsParams,
formatOptions,
disabledSearch = false,
...restProps
}: Props,
ref: Ref<any>,
) => {
const props = { ...restProps };
const { ctx, filterOption } = props;
if (isFunction(formatPropsValue)) {
props.value = formatPropsValue(props.value);
}
const [fetching, setFetching] = useState(false);
const [options, setOptions] = useState(props.options || props.source || []);
useImperativeHandle(ref, () => ({
emitSearch: (value: string) => {
loadOptions(value, true);
},
}));
useEffect(() => {
if (autoInit) {
loadOptions('', true);
}
}, []);
useEffect(() => {
setOptions(props.source || []);
}, [props.source]);
const fetchRef = useRef(0);
const loadOptions = (value: string, allowEmptyValue?: boolean) => {
setOptions([]);
if (disabledSearch) {
return;
}
if (!allowEmptyValue && !value) return;
fetchRef.current += 1;
const fetchId = fetchRef.current;
setFetching(true);
const fetchParams = formatFetchOptionsParams ? formatFetchOptionsParams(value, ctx) : [value];
// eslint-disable-next-line prefer-spread
fetchOptions.apply(null, fetchParams).then((newOptions) => {
if (fetchId !== fetchRef.current || !Array.isArray(newOptions)) {
return;
}
let finalOptions = newOptions;
if (formatOptions && isFunction(formatOptions)) {
finalOptions = formatOptions(newOptions, ctx);
}
finalOptions =
filterOption && Array.isArray(finalOptions)
? filterOption?.(finalOptions, ctx)
: finalOptions;
setOptions(finalOptions);
setFetching(false);
});
};
const debounceFetcher = useMemo(() => {
return debounce(loadOptions, debounceTimeout, {
trailing: true,
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [fetchOptions, debounceTimeout]);
return (
<Select
style={{ minWidth: '100px' }}
showSearch
allowClear
mode="multiple"
// onClear={() => {
// if (autoInit) {
// loadOptions('', true);
// } else {
// setOptions([]);
// }
// }}
onSearch={debounceFetcher}
{...props}
filterOption={false} // 保持对props中filterOption属性的复写不可变更位置
notFoundContent={
fetching ? <Spin size="small" /> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
}
loading={fetching}
>
{options.map((option: SelectOptions) => (
<Option value={option.value} key={option.value}>
{option.text || option.label}
</Option>
))}
</Select>
);
},
);
export default DebounceSelect;