antd/lib/table/interface#Key TypeScript Examples

The following examples show how to use antd/lib/table/interface#Key. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: utils.tsx    From next-basics with GNU General Public License v3.0 5 votes vote down vote up
export function filter(props: {
  tree: PlainObject | Array<PlainObject>;
  text: string | SearchInfoProps;
  config?: SearchConfig;
}) {
  const {
    tree,
    text,
    config = {
      supportFullWord: false,
      supportWordCase: false,
      supportKey: true,
    },
  } = props;
  const isSenior = isObject(text);
  const matchKey: Key[] = [];

  const isEqual = (v: string | PlainObject): boolean => {
    if (typeof v === "string") {
      let a = v;
      let b = text;
      if (!config.supportWordCase) {
        a = v.toLocaleLowerCase();
        b = (text as string).toLocaleLowerCase();
      }
      if (config.supportFullWord) {
        return a === b;
      } else {
        return a.includes(b as string);
      }
    } else {
      return isMatch(v, text as SearchInfoProps);
    }
  };

  const setMatchItem = (item: PlainObject): boolean => {
    item[symbolForHightlight as any] = true;
    item.key && matchKey.push(item.key);
    return true;
  };

  const filterNode = (item: PlainObject | string, text: string): boolean => {
    if (isObject(item) && item) {
      for (const [k, v] of Object.entries(item)) {
        if (!filterIgnoreKeys.includes(k)) {
          if (!isSenior && config.supportKey && isEqual(k)) {
            return setMatchItem(item);
          }
          if (Array.isArray(v)) {
            for (let i = 0; i < v.length; i++) {
              if (isObject(v[i])) {
                if (isSenior && isEqual(v[i])) {
                  return setMatchItem(item);
                }
                if (filterNode(v[i], text)) {
                  return setMatchItem(item);
                }
              } else if (
                !isSenior &&
                typeof v[i] === "string" &&
                isEqual(v[i])
              ) {
                return setMatchItem(item);
              }
            }
          } else if (isObject(v)) {
            if (isSenior && isEqual(v)) {
              return setMatchItem(item);
            } else if (filterNode(v, text)) {
              return setMatchItem(item);
            }
          } else if (!isSenior && typeof v === "string" && isEqual(v)) {
            return setMatchItem(item);
          }
        }
      }
    } else if (!isSenior) {
      return typeof item === "string" && isEqual(item);
    }
  };

  const nodeMatch = (node: PlainObject, text: string): boolean => {
    return filterNode(node, text);
  };

  const childMatch = (children: PlainObject): Array<PlainObject> => {
    /* eslint-disable @typescript-eslint/no-use-before-define */
    return children.reduce(getNodes, []);
  };

  const getNodes = (result: Array<PlainObject>, node: PlainObject) => {
    const isNodeMatch = nodeMatch(node, text as string);
    const children = childMatch(node?.children ?? []);

    if (children.length) {
      result.push({
        ...node,
        children,
      });
    } else if (isNodeMatch && !children.length) {
      result.push(node);
    }
    return result;
  };

  return {
    tree: tree.reduce(getNodes, []),
    matchKey,
  };
}
Example #2
Source File: SearchTree.tsx    From next-basics with GNU General Public License v3.0 4 votes vote down vote up
export function SearchTree(props: SearchTreeProps): React.ReactElement {
  const {
    treeData,
    searchConfig = {},
    titleClick,
    titleFocus,
    titleBlur,
  } = props;
  const searchTreeRef = useRef<HTMLDivElement>(null);
  const searchWapperRef = useRef<HTMLDivElement>(null);
  const [value, setValue] = useState("");
  const baseTree = buildTree(treeData?.storyboard);
  const [tree, setTree] = useState(baseTree);
  const [expandedKeys, setExpandedKeys] = useState<Key[]>([]);
  const [forceUpdate, setForceUpdate] = useState<number>(0);
  const [supportKey, setSupportKey] = useState<boolean>(
    searchConfig.supportKey ?? true
  );
  const [supportWordCase, setSupportWordCase] = useState<boolean>(
    searchConfig.supportWordCase ?? false
  );
  const [supportFullWord, setSupportFullWord] = useState<boolean>(
    searchConfig.supportFullWord ?? false
  );
  const [maxHeight, setMaxHeight] = useState<number>(0);

  const [searchContentDetail, setSearchContentDetail] = useState<{
    info: PlainObject;
  }>();

  const setFilterTree = useRef(
    debounce((filterValue, searchConfig = {}) => {
      if (filterValue !== "") {
        const { tree, matchKey } = filter({
          tree: cloneDeep(baseTree),
          text: filterValue,
          config: Object.assign(
            {},
            {
              supportFullWord,
              supportWordCase,
              supportKey,
            },
            searchConfig
          ),
        });
        setExpandedKeys(matchKey);
        setTree(tree);
        setForceUpdate(Math.random());
      } else {
        setExpandedKeys([]);
        setTree(baseTree);
      }
    }, 300)
  ).current;

  const handleAutoSearch = (fields: Field[]): void => {
    if (fields) {
      const searchInfo: SearchInfoProps = {};
      fields.forEach((item) => {
        const text = item.values[0];
        if (
          text === "" ||
          text === null ||
          (Array.isArray(text) && !text.length)
        )
          return;
        searchInfo[item.id] = {
          op: item.currentCondition.operations[0].operator,
          text: text,
        };
      });
      if (Object.keys(searchInfo).length) {
        setFilterTree(searchInfo);
      } else {
        setFilterTree("");
      }
    }
  };

  const handleFilterChange = (
    event: React.ChangeEvent<HTMLInputElement>
  ): void => {
    setValue(event.target.value);
    setFilterTree(event.target.value.trim(), {
      supportFullWord,
      supportWordCase,
      supportKey,
    });
  };

  const renderTitle = (nodeData: PlainObject): JSX.Element =>
    titleRender({
      nodeData,
    });

  const onSelect = (_selectedKeys: React.Key[], item: PlainObject): void => {
    titleClick?.({
      info: item.node[NODE_INFO],
    });
    setSearchContentDetail({
      info: item.node[NODE_INFO],
    });
  };

  const onMouseEnter = (info: NodeMouseEventParams): void =>
    titleFocus?.({
      info: (info.node as PlainObject)[NODE_INFO],
    });

  const onMouseLeave = (info: NodeMouseEventParams): void =>
    titleBlur?.({
      info: (info.node as PlainObject)[NODE_INFO],
    });

  const handleClickIcon = (type: searchType): void => {
    switch (type) {
      case searchType.fullWord:
        setSupportFullWord(!supportFullWord);
        setFilterTree(value, {
          supportFullWord: !supportFullWord,
        });
        break;
      case searchType.key:
        setSupportKey(!supportKey);
        setFilterTree(value, {
          supportKey: !supportKey,
        });
        break;
      case searchType.ingoreCase:
        setSupportWordCase(!supportWordCase);
        setFilterTree(value, {
          supportWordCase: !supportWordCase,
        });
        break;
    }
  };

  const renderInputSuffixIcon = (): JSX.Element => {
    return (
      <>
        <span title="区分大小写">
          <GeneralIcon
            icon={{
              color: supportWordCase ? "orange" : "#8c8c8c",
              icon: "ingore-case",
              category: "default",
              lib: "easyops",
            }}
            size={20}
            style={{
              marginRight: 5,
            }}
            onClick={() => handleClickIcon(searchType.ingoreCase)}
          />
        </span>
        <span title="全字匹配">
          <GeneralIcon
            icon={{
              color: supportFullWord ? "orange" : "#8c8c8c",
              category: "default",
              icon: "full-word",
              lib: "easyops",
            }}
            size={20}
            style={{
              marginRight: 5,
            }}
            onClick={() => handleClickIcon(searchType.fullWord)}
          />
        </span>
        <span title="支持Key查询">
          <GeneralIcon
            icon={{
              color: supportKey ? "orange" : "#8c8c8c",
              category: "default",
              icon: "key",
              lib: "easyops",
            }}
            size={20}
            style={{
              marginRight: 5,
            }}
            onClick={() => handleClickIcon(searchType.key)}
          />
        </span>
      </>
    );
  };

  useEffect(() => {
    const resizeObserver = new ResizeObserver(() => {
      const maxHeight =
        searchTreeRef.current.getBoundingClientRect().height -
        searchWapperRef.current.getBoundingClientRect().height;
      setMaxHeight(maxHeight);
    });
    resizeObserver.observe(searchTreeRef.current);
    resizeObserver.observe(searchWapperRef.current);
    return () => {
      resizeObserver.disconnect();
    };
  }, []);

  useEffect(() => {
    setTree(buildTree(treeData?.storyboard));
  }, [treeData]);

  return (
    <div ref={searchTreeRef} style={{ height: "100%" }}>
      <div ref={searchWapperRef}>
        <Input
          placeholder="输入关键字搜索StoryBoard"
          value={value}
          onChange={handleFilterChange}
          suffix={renderInputSuffixIcon()}
        />
        <div style={{ marginTop: 10 }}>
          <InstanceList
            searchDisabled
            hideInstanceList
            relatedToMeDisabled
            showHiddenInfoDisabled
            objectId={searchBoardModel.objectId}
            objectList={[searchBoardModel as ModelCmdbObject]}
            disabledDefaultFields
            autoSearch={handleAutoSearch}
          />
        </div>
      </div>
      {tree.length ? (
        <div className={className(styles.searchWrapper)}>
          <div className={className(styles.SearchTree)}>
            <Tree
              key={forceUpdate}
              onExpand={setExpandedKeys}
              expandedKeys={expandedKeys}
              showIcon={true}
              treeData={tree}
              virtual={true}
              height={maxHeight}
              titleRender={renderTitle}
              onSelect={onSelect}
              onMouseEnter={onMouseEnter}
              onMouseLeave={onMouseLeave}
            />
          </div>
          <div className={className(styles.searchContent)}>
            {searchContentDetail && props.searchContent && (
              <BrickAsComponent
                useBrick={props.searchContent.useBrick}
                data={searchContentDetail}
              />
            )}
          </div>
        </div>
      ) : (
        <div
          style={{
            color: "#8c8c8c",
            textAlign: "center",
            margin: 20,
          }}
        >
          = = Search Empty = =
        </div>
      )}
    </div>
  );
}