PlaylistPage.tsx 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. import React, { FC, useState } from 'react';
  2. import { connect, MapStateToProps } from 'react-redux';
  3. import { useDebounce } from 'react-use';
  4. import { NavModel } from '@grafana/data';
  5. import { ConfirmModal } from '@grafana/ui';
  6. import Page from 'app/core/components/Page/Page';
  7. import PageActionBar from 'app/core/components/PageActionBar/PageActionBar';
  8. import { getNavModel } from 'app/core/selectors/navModel';
  9. import { contextSrv } from 'app/core/services/context_srv';
  10. import { StoreState } from 'app/types';
  11. import EmptyListCTA from '../../core/components/EmptyListCTA/EmptyListCTA';
  12. import { GrafanaRouteComponentProps } from '../../core/navigation/types';
  13. import { EmptyQueryListBanner } from './EmptyQueryListBanner';
  14. import { PlaylistPageList } from './PlaylistPageList';
  15. import { StartModal } from './StartModal';
  16. import { deletePlaylist, getAllPlaylist } from './api';
  17. import { PlaylistDTO } from './types';
  18. interface ConnectedProps {
  19. navModel: NavModel;
  20. }
  21. export interface PlaylistPageProps extends ConnectedProps, GrafanaRouteComponentProps {}
  22. export const PlaylistPage: FC<PlaylistPageProps> = ({ navModel }) => {
  23. const [searchQuery, setSearchQuery] = useState('');
  24. const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(searchQuery);
  25. const [hasFetched, setHasFetched] = useState(false);
  26. const [startPlaylist, setStartPlaylist] = useState<PlaylistDTO | undefined>();
  27. const [playlistToDelete, setPlaylistToDelete] = useState<PlaylistDTO | undefined>();
  28. const [forcePlaylistsFetch, setForcePlaylistsFetch] = useState(0);
  29. const [playlists, setPlaylists] = useState<PlaylistDTO[]>([]);
  30. useDebounce(
  31. async () => {
  32. const playlists = await getAllPlaylist(searchQuery);
  33. if (!hasFetched) {
  34. setHasFetched(true);
  35. }
  36. setPlaylists(playlists);
  37. setDebouncedSearchQuery(searchQuery);
  38. },
  39. 350,
  40. [forcePlaylistsFetch, searchQuery]
  41. );
  42. const hasPlaylists = playlists && playlists.length > 0;
  43. const onDismissDelete = () => setPlaylistToDelete(undefined);
  44. const onDeletePlaylist = () => {
  45. if (!playlistToDelete) {
  46. return;
  47. }
  48. deletePlaylist(playlistToDelete.uid).finally(() => {
  49. setForcePlaylistsFetch(forcePlaylistsFetch + 1);
  50. setPlaylistToDelete(undefined);
  51. });
  52. };
  53. const emptyListBanner = (
  54. <EmptyListCTA
  55. title="There are no playlists created yet"
  56. buttonIcon="plus"
  57. buttonLink="playlists/new"
  58. buttonTitle="Create Playlist"
  59. buttonDisabled={!contextSrv.isEditor}
  60. proTip="You can use playlists to cycle dashboards on TVs without user control"
  61. proTipLink="http://docs.grafana.org/reference/playlist/"
  62. proTipLinkTitle="Learn more"
  63. proTipTarget="_blank"
  64. />
  65. );
  66. const showSearch = playlists.length > 0 || searchQuery.length > 0 || debouncedSearchQuery.length > 0;
  67. return (
  68. <Page navModel={navModel}>
  69. <Page.Contents isLoading={!hasFetched}>
  70. {showSearch && (
  71. <PageActionBar
  72. searchQuery={searchQuery}
  73. linkButton={contextSrv.isEditor && { title: 'New playlist', href: '/playlists/new' }}
  74. setSearchQuery={setSearchQuery}
  75. />
  76. )}
  77. {!hasPlaylists && searchQuery ? (
  78. <EmptyQueryListBanner />
  79. ) : (
  80. <PlaylistPageList
  81. playlists={playlists}
  82. setStartPlaylist={setStartPlaylist}
  83. setPlaylistToDelete={setPlaylistToDelete}
  84. />
  85. )}
  86. {!showSearch && emptyListBanner}
  87. {playlistToDelete && (
  88. <ConfirmModal
  89. title={playlistToDelete.name}
  90. confirmText="Delete"
  91. body={`Are you sure you want to delete '${playlistToDelete.name}' playlist?`}
  92. onConfirm={onDeletePlaylist}
  93. isOpen={Boolean(playlistToDelete)}
  94. onDismiss={onDismissDelete}
  95. />
  96. )}
  97. {startPlaylist && <StartModal playlist={startPlaylist} onDismiss={() => setStartPlaylist(undefined)} />}
  98. </Page.Contents>
  99. </Page>
  100. );
  101. };
  102. const mapStateToProps: MapStateToProps<ConnectedProps, {}, StoreState> = (state: StoreState) => ({
  103. navModel: getNavModel(state.navIndex, 'playlists'),
  104. });
  105. export default connect(mapStateToProps)(PlaylistPage);