import { css } from '@emotion/css'; import { useState } from 'react'; import { useLocation } from 'react-router-dom-v5-compat'; import { SelectableValue, GrafanaTheme2, PluginType } from '@grafana/data'; import { locationSearchToObject } from '@grafana/runtime'; import { Select, RadioButtonGroup, useStyles2, Tooltip, Field, TextLink } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import { t, Trans } from 'app/core/internationalization'; import { getNavModel } from 'app/core/selectors/navModel'; import { ROUTES as CONNECTIONS_ROUTES } from 'app/features/connections/constants'; import { useSelector } from 'app/types'; import { HorizontalGroup } from '../components/HorizontalGroup'; import { PluginList } from '../components/PluginList'; import { RoadmapLinks } from '../components/RoadmapLinks'; import { SearchField } from '../components/SearchField'; import UpdateAllButton from '../components/UpdateAllButton'; import { UpdateAllModal } from '../components/UpdateAllModal'; import { Sorters } from '../helpers'; import { useHistory } from '../hooks/useHistory'; import { useGetAll, useGetUpdatable, useIsRemotePluginsAvailable } from '../state/hooks'; export default function Browse() { const location = useLocation(); const locationSearch = locationSearchToObject(location.search); const navModel = useSelector((state) => getNavModel(state.navIndex, 'plugins')); const styles = useStyles2(getStyles); const history = useHistory(); const remotePluginsAvailable = useIsRemotePluginsAvailable(); const keyword = locationSearch.q?.toString() || ''; const filterBy = locationSearch.filterBy?.toString() || 'all'; const filterByType = (locationSearch.filterByType as PluginType | 'all') || 'all'; const sortBy = (locationSearch.sortBy as Sorters) || Sorters.nameAsc; const { isLoading, error, plugins } = useGetAll( { keyword, type: filterByType !== 'all' ? filterByType : undefined, isInstalled: filterBy === 'installed' ? true : undefined, hasUpdate: filterBy === 'has-update' ? true : undefined, }, sortBy ); const filterByOptions = [ { value: 'all', label: 'All' }, { value: 'installed', label: 'Installed' }, { value: 'has-update', label: 'New Updates' }, ]; const { isLoading: areUpdatesLoading, updatablePlugins } = useGetUpdatable(); const [showUpdateModal, setShowUpdateModal] = useState(false); const disableUpdateAllButton = updatablePlugins.length <= 0 || areUpdatesLoading; const onFilterByChange = (value: string) => { history.push({ query: { filterBy: value } }); }; const onFilterByTypeChange = (value: SelectableValue) => { history.push({ query: { filterByType: value.value } }); }; const onSearch = (q: string) => { history.push({ query: { filterBy, filterByType, q } }); }; const onUpdateAll = () => { setShowUpdateModal(true); }; // How should we handle errors? if (error) { console.error(error.message); return null; } const subTitle = (
Extend the Grafana experience with panel plugins and apps. To find more data sources go to{' '} Connections.
); const updateAllButton = ( ); return ( {/* Filter by type */}