/** * Copyright 2020 Baidu Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import {ChartCollapseTitle as ChartCollapseTitleLoader, Chart as ChartLoader} from '~/components/Loader/ChartPage'; import React, {FunctionComponent, PropsWithChildren, useCallback, useEffect, useMemo, useState} from 'react'; import {Trans, useTranslation} from 'react-i18next'; import {WithStyled, headerHeight, link, rem, transitionProps} from '~/utils/style'; import Chart from '~/components/Chart'; import ChartCollapse from '~/components/ChartCollapse'; import Pagination from '~/components/Pagination'; import SearchInput from '~/components/SearchInput'; import groupBy from 'lodash/groupBy'; import styled from 'styled-components'; import useSearchValue from '~/hooks/useSearchValue'; const PUBLIC_PATH: string = import.meta.env.SNOWPACK_PUBLIC_PATH; const StyledPagination = styled(Pagination)` margin-top: ${rem(20)}; `; const Wrapper = styled.div` display: flex; flex-wrap: wrap; justify-content: flex-start; align-items: stretch; align-content: flex-start; margin-bottom: -${rem(20)}; > * { margin: 0 ${rem(20)} ${rem(20)} 0; flex-shrink: 0; flex-grow: 0; &.maximized { margin-right: 0; } } `; const Search = styled.div` width: ${rem(280)}; margin-bottom: ${rem(16)}; `; const Empty = styled.div<{height?: string}>` width: 100%; text-align: center; font-size: ${rem(16)}; color: var(--text-lighter-color); line-height: ${rem(24)}; height: ${props => props.height ?? 'auto'}; padding: ${rem(320)} 0 ${rem(70)}; background-color: var(--background-color); background-image: url(${`${PUBLIC_PATH}/images/empty.svg`}); background-repeat: no-repeat; background-position: calc(50% + ${rem(25)}) ${rem(70)}; background-size: ${rem(280)} ${rem(244)}; ${transitionProps(['color', 'background-color'])} ${link} `; type Item = { id?: string; label: string; }; export interface WithChart { (item: T & {cid: symbol}, index: number): React.ReactNode; } type ChartPageProps = { items?: T[]; running?: boolean; loading?: boolean | React.ReactNode; chartSize?: { width?: string; height?: string; }; withChart?: WithChart; }; const ChartPage = ({ items, loading, chartSize, withChart, className }: PropsWithChildren & WithStyled>): ReturnType => { const {t} = useTranslation('common'); const [page, setPage] = useState(1); const pageSize = 12; const [inputValue, setInputValue] = useState(''); const searchValue = useSearchValue(inputValue); const matchedTags = useMemo(() => { try { const pattern = new RegExp(searchValue); return items?.filter(tag => pattern.test(tag.label)) ?? []; } catch { return []; } }, [items, searchValue]); const pageMatchedTags = useMemo(() => matchedTags?.slice((page - 1) * pageSize, page * pageSize) ?? [], [ matchedTags, page ]); useEffect(() => { setPage(1); }, [searchValue]); const groupedItems = useMemo( () => Object.entries(groupBy(items ?? [], item => item.label.split('/')[0])).sort(([a], [b]) => { const ua = a.toUpperCase(); const ub = b.toUpperCase(); if (ua < ub) { return -1; } if (ua > ub) { return 1; } return 0; }), [items] ); const total = useMemo(() => Math.ceil(matchedTags.length / pageSize), [matchedTags]); const withCharts = useCallback( (charts: T[], search?: boolean) => ( {loading ? ( Array.from({length: 2}).map((_, index) => ( {loading === true ? : loading} )) ) : charts.length ? ( charts.map((item, j) => { const cid = Symbol(item.label); return ( {withChart?.({...item, cid}, j)} ); }) ) : ( {search ? ( Nothing found. Please try again with another word.
Or you can setInputValue('')}>see all charts.
) : ( t('common:empty') )}
)}
), [loading, t, chartSize?.width, chartSize?.height, withChart] ); const content = useMemo(() => { if (loading) { return Array.from({length: 3}).map((_, index) => ( } opened={!index}> {withCharts([])} )); } if (searchValue) { return ( {withCharts(pageMatchedTags, true)} {pageMatchedTags.length ? : null} ); } if (groupedItems.length) { return groupedItems.map((groupedItem, i) => ( {withCharts(groupedItem[1])} )); } return ( Nothing selected.
Please select display data from right side.
); }, [groupedItems, loading, matchedTags.length, page, pageMatchedTags, searchValue, t, total, withCharts]); return (
setInputValue(value)} /> {content}
); }; export default ChartPage;