From 77f7e8dafc5f3afd111b1d035ca03c50100ba543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 20 Jul 2022 17:26:52 +0200 Subject: [PATCH] PageLayouts: Updates dashboard section routes with navId (#52175) * First stab at new page layouts behind feature toggle * Simplifying PageHeader * Progress on a new model that can more easily support new and old page layouts * Progress * rename folder * Progress * Minor change * fixes * Fixing tests * Make breadcrumbs work * Add tests for old Page component * Adding tests for new Page component and behavior * fixing page header test * Fixed test * Moving user profile routes to navId * PageLayouts: Updates dashboards routes with navId * added missing navId * AppChrome outside route * Renaming folder * Minor fix * Updated * Fixing StoragePage * Updated * Updating translation ids * Updated snapshot * update nav translation ids (yes this is confusing) Co-authored-by: Ashley Harrison Co-authored-by: joshhunt --- .betterer.results | 2 +- pkg/api/index.go | 14 ++++----- .../NavBar/navBarItem-translations.ts | 17 ++++++----- .../AccessControlFolderPermissions.tsx | 6 ++-- .../app/features/folders/FolderAlerting.tsx | 4 +-- .../folders/FolderLibraryPanelsPage.tsx | 6 ++-- .../features/folders/FolderPermissions.tsx | 8 ++--- .../folders/FolderSettingsPage.test.tsx | 2 +- .../features/folders/FolderSettingsPage.tsx | 6 ++-- .../FolderSettingsPage.test.tsx.snap | 4 +-- .../components/NewDashboardsFolder.tsx | 10 ++----- .../library-panels/LibraryPanelsPage.tsx | 23 +++------------ .../manage-dashboards/DashboardImportPage.tsx | 6 ++-- .../manage-dashboards/SnapshotListPage.tsx | 23 +++------------ .../playlist/PlaylistEditPage.test.tsx | 13 +-------- .../features/playlist/PlaylistEditPage.tsx | 20 +++---------- public/app/features/playlist/PlaylistForm.tsx | 4 +-- .../playlist/PlaylistNewPage.test.tsx | 21 ++------------ .../app/features/playlist/PlaylistNewPage.tsx | 24 +++------------ .../features/playlist/PlaylistPage.test.tsx | 29 ++----------------- public/app/features/playlist/PlaylistPage.tsx | 22 +++----------- .../search/components/DashboardListPage.tsx | 29 ++++++------------- public/app/routes/routes.tsx | 5 ++-- 23 files changed, 80 insertions(+), 218 deletions(-) diff --git a/.betterer.results b/.betterer.results index 111b48b197a..c2bd381ecad 100644 --- a/.betterer.results +++ b/.betterer.results @@ -83,7 +83,7 @@ exports[`no enzyme tests`] = { "public/app/features/dimensions/editors/ThresholdsEditor/ThresholdsEditor.test.tsx:4164297658": [ [0, 17, 13, "RegExp match", "2409514259"] ], - "public/app/features/folders/FolderSettingsPage.test.tsx:1109052730": [ + "public/app/features/folders/FolderSettingsPage.test.tsx:1208063654": [ [0, 19, 13, "RegExp match", "2409514259"] ], "public/app/plugins/datasource/cloudwatch/components/ConfigEditor.test.tsx:4057721851": [ diff --git a/pkg/api/index.go b/pkg/api/index.go index de644dabb94..dacaaabb94f 100644 --- a/pkg/api/index.go +++ b/pkg/api/index.go @@ -443,23 +443,23 @@ func (hs *HTTPServer) buildDashboardNavLinks(c *models.ReqContext, hasEditPerm b dashboardChildNavs := []*dtos.NavLink{} dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{ - Text: "Browse", Id: "manage-dashboards", Url: hs.Cfg.AppSubURL + "/dashboards", Icon: "sitemap", + Text: "Browse", Id: "dashboards/browse", Url: hs.Cfg.AppSubURL + "/dashboards", Icon: "sitemap", }) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{ - Text: "Playlists", Id: "playlists", Url: hs.Cfg.AppSubURL + "/playlists", Icon: "presentation-play", + Text: "Playlists", Id: "dashboards/playlists", Url: hs.Cfg.AppSubURL + "/playlists", Icon: "presentation-play", }) if c.IsSignedIn { dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{ Text: "Snapshots", - Id: "snapshots", + Id: "dashboards/snapshots", Url: hs.Cfg.AppSubURL + "/dashboard/snapshots", Icon: "camera", }) dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{ Text: "Library panels", - Id: "library-panels", + Id: "dashboards/library-panels", Url: hs.Cfg.AppSubURL + "/library-panels", Icon: "library-panel", }) @@ -481,20 +481,20 @@ func (hs *HTTPServer) buildDashboardNavLinks(c *models.ReqContext, hasEditPerm b if hasAccess(hasEditPermInAnyFolder, ac.EvalPermission(dashboards.ActionDashboardsCreate)) { dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{ - Text: "New dashboard", Icon: "plus", Url: hs.Cfg.AppSubURL + "/dashboard/new", HideFromTabs: true, Id: "new-dashboard", ShowIconInNavbar: true, + Text: "New dashboard", Icon: "plus", Url: hs.Cfg.AppSubURL + "/dashboard/new", HideFromTabs: true, Id: "dashboards/new", ShowIconInNavbar: true, }) } if hasAccess(ac.ReqOrgAdminOrEditor, ac.EvalPermission(dashboards.ActionFoldersCreate)) { dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{ - Text: "New folder", SubTitle: "Create a new folder to organize your dashboards", Id: "new-folder", + Text: "New folder", SubTitle: "Create a new folder to organize your dashboards", Id: "dashboards/folder/new", Icon: "plus", Url: hs.Cfg.AppSubURL + "/dashboards/folder/new", HideFromTabs: true, ShowIconInNavbar: true, }) } if hasAccess(hasEditPermInAnyFolder, ac.EvalPermission(dashboards.ActionDashboardsCreate)) { dashboardChildNavs = append(dashboardChildNavs, &dtos.NavLink{ - Text: "Import", SubTitle: "Import dashboard from file or Grafana.com", Id: "import", Icon: "plus", + Text: "Import", SubTitle: "Import dashboard from file or Grafana.com", Id: "dashboards/import", Icon: "plus", Url: hs.Cfg.AppSubURL + "/dashboard/import", HideFromTabs: true, ShowIconInNavbar: true, }) } diff --git a/public/app/core/components/NavBar/navBarItem-translations.ts b/public/app/core/components/NavBar/navBarItem-translations.ts index 7f517bf3f47..9fa0e2842a8 100644 --- a/public/app/core/components/NavBar/navBarItem-translations.ts +++ b/public/app/core/components/NavBar/navBarItem-translations.ts @@ -4,7 +4,10 @@ import { defineMessage } from '@lingui/macro'; // Maps the ID of the nav item to a translated phrase to later pass to // Because the navigation content is dynamic (defined in the backend), we can not use // the normal inline message definition method. -// Keys MUST match the ID of the navigation item, defined in the backend. + +// The keys of the TRANSLATED_MENU_ITEMS object (NOT the id inside the defineMessage function) +// must match the ID of the navigation item, as defined in the backend nav model + // see pkg/api/index.go const TRANSLATED_MENU_ITEMS: Record = { home: defineMessage({ id: 'nav.home', message: 'Home' }), @@ -18,12 +21,12 @@ const TRANSLATED_MENU_ITEMS: Record = { starred: defineMessage({ id: 'nav.starred', message: 'Starred' }), 'starred-empty': defineMessage({ id: 'nav.starred-empty', message: 'Your starred dashboards will appear here' }), dashboards: defineMessage({ id: 'nav.dashboards', message: 'Dashboards' }), - 'manage-dashboards': defineMessage({ id: 'nav.manage-dashboards', message: 'Browse' }), - playlists: defineMessage({ id: 'nav.playlists', message: 'Playlists' }), - snapshots: defineMessage({ id: 'nav.snapshots', message: 'Snapshots' }), - 'library-panels': defineMessage({ id: 'nav.library-panels', message: 'Library panels' }), - 'new-dashboard': defineMessage({ id: 'nav.new-dashboard', message: 'New dashboard' }), - 'new-folder': defineMessage({ id: 'nav.new-folder', message: 'New folder' }), + 'dashboards/browse': defineMessage({ id: 'nav.manage-dashboards', message: 'Browse' }), + 'dashboards/playlists': defineMessage({ id: 'nav.playlists', message: 'Playlists' }), + 'dashboards/snapshots': defineMessage({ id: 'nav.snapshots', message: 'Snapshots' }), + 'dashboards/library-panels': defineMessage({ id: 'nav.library-panels', message: 'Library panels' }), + 'dashboards/new': defineMessage({ id: 'nav.new-dashboard', message: 'New dashboard' }), + 'dashboards/folder/new': defineMessage({ id: 'nav.new-folder', message: 'New folder' }), explore: defineMessage({ id: 'nav.explore', message: 'Explore' }), diff --git a/public/app/features/folders/AccessControlFolderPermissions.tsx b/public/app/features/folders/AccessControlFolderPermissions.tsx index 325b69eb406..a3db00633b9 100644 --- a/public/app/features/folders/AccessControlFolderPermissions.tsx +++ b/public/app/features/folders/AccessControlFolderPermissions.tsx @@ -17,7 +17,7 @@ function mapStateToProps(state: StoreState, props: RouteProps) { const uid = props.match.params.uid; return { uid: uid, - navModel: getNavModel(state.navIndex, `folder-permissions-${uid}`, getLoadingNav(1)), + pageNav: getNavModel(state.navIndex, `folder-permissions-${uid}`, getLoadingNav(1)), }; } @@ -28,7 +28,7 @@ const mapDispatchToProps = { const connector = connect(mapStateToProps, mapDispatchToProps); export type Props = ConnectedProps; -export const AccessControlFolderPermissions = ({ uid, getFolderByUid, navModel }: Props) => { +export const AccessControlFolderPermissions = ({ uid, getFolderByUid, pageNav }: Props) => { useEffect(() => { getFolderByUid(uid); }, [getFolderByUid, uid]); @@ -36,7 +36,7 @@ export const AccessControlFolderPermissions = ({ uid, getFolderByUid, navModel } const canSetPermissions = contextSrv.hasPermission(AccessControlAction.FoldersPermissionsWrite); return ( - + diff --git a/public/app/features/folders/FolderAlerting.tsx b/public/app/features/folders/FolderAlerting.tsx index 25785b74949..ec4c7615356 100644 --- a/public/app/features/folders/FolderAlerting.tsx +++ b/public/app/features/folders/FolderAlerting.tsx @@ -20,12 +20,12 @@ const FolderAlerting = ({ match }: OwnProps) => { const folder = useSelector((state: StoreState) => state.folder); const uid = match.params.uid; - const navModel = getNavModel(navIndex, `folder-alerting-${uid}`, getLoadingNav(1)); + const pageNav = getNavModel(navIndex, `folder-alerting-${uid}`, getLoadingNav(1)); const { loading } = useAsync(async () => dispatch(getFolderByUid(uid)), [getFolderByUid, uid]); return ( - + diff --git a/public/app/features/folders/FolderLibraryPanelsPage.tsx b/public/app/features/folders/FolderLibraryPanelsPage.tsx index a645f34bb51..24ae4ab1534 100644 --- a/public/app/features/folders/FolderLibraryPanelsPage.tsx +++ b/public/app/features/folders/FolderLibraryPanelsPage.tsx @@ -19,7 +19,7 @@ export interface OwnProps extends GrafanaRouteComponentProps<{ uid: string }> {} const mapStateToProps = (state: StoreState, props: OwnProps) => { const uid = props.match.params.uid; return { - navModel: getNavModel(state.navIndex, `folder-library-panels-${uid}`, getLoadingNav(1)), + pageNav: getNavModel(state.navIndex, `folder-library-panels-${uid}`, getLoadingNav(1)), folderUid: uid, folder: state.folder, }; @@ -33,12 +33,12 @@ const connector = connect(mapStateToProps, mapDispatchToProps); export type Props = OwnProps & ConnectedProps; -export function FolderLibraryPanelsPage({ navModel, getFolderByUid, folderUid, folder }: Props): JSX.Element { +export function FolderLibraryPanelsPage({ pageNav, getFolderByUid, folderUid, folder }: Props): JSX.Element { const { loading } = useAsync(async () => await getFolderByUid(folderUid), [getFolderByUid, folderUid]); const [selected, setSelected] = useState(undefined); return ( - + {} const mapStateToProps = (state: StoreState, props: OwnProps) => { const uid = props.match.params.uid; return { - navModel: getNavModel(state.navIndex, `folder-permissions-${uid}`, getLoadingNav(1)), + pageNav: getNavModel(state.navIndex, `folder-permissions-${uid}`, getLoadingNav(1)), folderUid: uid, folder: state.folder, }; @@ -83,12 +83,12 @@ export class FolderPermissions extends PureComponent { }; render() { - const { navModel, folder } = this.props; + const { pageNav, folder } = this.props; const { isAdding } = this.state; if (folder.id === 0) { return ( - + @@ -99,7 +99,7 @@ export class FolderPermissions extends PureComponent { const folderInfo = { title: folder.title, url: folder.url, id: folder.id }; return ( - +

Folder Permissions

diff --git a/public/app/features/folders/FolderSettingsPage.test.tsx b/public/app/features/folders/FolderSettingsPage.test.tsx index 65f024996d3..e6136f0092f 100644 --- a/public/app/features/folders/FolderSettingsPage.test.tsx +++ b/public/app/features/folders/FolderSettingsPage.test.tsx @@ -11,7 +11,7 @@ import { setFolderTitle } from './state/reducers'; const setup = (propOverrides?: object) => { const props: Props = { ...getRouteComponentProps(), - navModel: {} as NavModel, + pageNav: {} as NavModel, folderUid: '1234', folder: { id: 0, diff --git a/public/app/features/folders/FolderSettingsPage.tsx b/public/app/features/folders/FolderSettingsPage.tsx index ecb47bb0de2..3936f4383fb 100644 --- a/public/app/features/folders/FolderSettingsPage.tsx +++ b/public/app/features/folders/FolderSettingsPage.tsx @@ -20,7 +20,7 @@ export interface OwnProps extends GrafanaRouteComponentProps<{ uid: string }> {} const mapStateToProps = (state: StoreState, props: OwnProps) => { const uid = props.match.params.uid; return { - navModel: getNavModel(state.navIndex, `folder-settings-${uid}`, getLoadingNav(2)), + pageNav: getNavModel(state.navIndex, `folder-settings-${uid}`, getLoadingNav(2)), folderUid: uid, folder: state.folder, }; @@ -84,10 +84,10 @@ export class FolderSettingsPage extends PureComponent { }; render() { - const { navModel, folder } = this.props; + const { pageNav, folder } = this.props; return ( - +

Folder settings

diff --git a/public/app/features/folders/__snapshots__/FolderSettingsPage.test.tsx.snap b/public/app/features/folders/__snapshots__/FolderSettingsPage.test.tsx.snap index 1a334028040..955a524fb96 100644 --- a/public/app/features/folders/__snapshots__/FolderSettingsPage.test.tsx.snap +++ b/public/app/features/folders/__snapshots__/FolderSettingsPage.test.tsx.snap @@ -2,7 +2,7 @@ exports[`Render should enable save button 1`] = ` ({ - navModel: getNavModel(state.navIndex, 'manage-dashboards'), -}); - const mapDispatchToProps = { createNewFolder, }; -const connector = connect(mapStateToProps, mapDispatchToProps); +const connector = connect(null, mapDispatchToProps); interface OwnProps {} @@ -47,7 +41,7 @@ export class NewDashboardsFolder extends PureComponent { render() { return ( - +

New dashboard folder

diff --git a/public/app/features/library-panels/LibraryPanelsPage.tsx b/public/app/features/library-panels/LibraryPanelsPage.tsx index af435231e7a..0fc5d2ad6ae 100644 --- a/public/app/features/library-panels/LibraryPanelsPage.tsx +++ b/public/app/features/library-panels/LibraryPanelsPage.tsx @@ -1,31 +1,16 @@ -import React, { FC, useState } from 'react'; -import { connect, ConnectedProps } from 'react-redux'; +import React, { useState } from 'react'; import { Page } from 'app/core/components/Page/Page'; -import { GrafanaRouteComponentProps } from '../../core/navigation/types'; -import { getNavModel } from '../../core/selectors/navModel'; -import { StoreState } from '../../types'; - import { LibraryPanelsSearch } from './components/LibraryPanelsSearch/LibraryPanelsSearch'; import { OpenLibraryPanelModal } from './components/OpenLibraryPanelModal/OpenLibraryPanelModal'; import { LibraryElementDTO } from './types'; -const mapStateToProps = (state: StoreState) => ({ - navModel: getNavModel(state.navIndex, 'library-panels'), -}); - -const connector = connect(mapStateToProps, undefined); - -interface OwnProps extends GrafanaRouteComponentProps {} - -type Props = OwnProps & ConnectedProps; - -export const LibraryPanelsPage: FC = ({ navModel }) => { +export const LibraryPanelsPage = () => { const [selected, setSelected] = useState(undefined); return ( - + {selected ? setSelected(undefined)} libraryPanel={selected} /> : null} @@ -34,4 +19,4 @@ export const LibraryPanelsPage: FC = ({ navModel }) => { ); }; -export default connect(mapStateToProps)(LibraryPanelsPage); +export default LibraryPanelsPage; diff --git a/public/app/features/manage-dashboards/DashboardImportPage.tsx b/public/app/features/manage-dashboards/DashboardImportPage.tsx index 365a7eabd1b..cdcf8f78171 100644 --- a/public/app/features/manage-dashboards/DashboardImportPage.tsx +++ b/public/app/features/manage-dashboards/DashboardImportPage.tsx @@ -22,7 +22,6 @@ import { import appEvents from 'app/core/app_events'; import { Page } from 'app/core/components/Page/Page'; import { GrafanaRouteComponentProps } from 'app/core/navigation/types'; -import { getNavModel } from 'app/core/selectors/navModel'; import { StoreState } from 'app/types'; import { cleanUpAction } from '../../core/actions/cleanUp'; @@ -40,7 +39,6 @@ type OwnProps = Themeable2 & GrafanaRouteComponentProps<{}, DashboardImportPageR const IMPORT_STARTED_EVENT_NAME = 'dashboard_import_loaded'; const mapStateToProps = (state: StoreState) => ({ - navModel: getNavModel(state.navIndex, 'import', undefined, true), loadingState: state.importDashboard.state, }); @@ -189,10 +187,10 @@ class UnthemedDashboardImport extends PureComponent { } render() { - const { loadingState, navModel } = this.props; + const { loadingState } = this.props; return ( - + {loadingState === LoadingState.Loading && ( diff --git a/public/app/features/manage-dashboards/SnapshotListPage.tsx b/public/app/features/manage-dashboards/SnapshotListPage.tsx index ae16793ca0f..3bc6f993ec2 100644 --- a/public/app/features/manage-dashboards/SnapshotListPage.tsx +++ b/public/app/features/manage-dashboards/SnapshotListPage.tsx @@ -1,23 +1,12 @@ -import React, { FC } from 'react'; -import { MapStateToProps, connect } from 'react-redux'; +import React from 'react'; -import { NavModel } from '@grafana/data'; import { Page } from 'app/core/components/Page/Page'; -import { getNavModel } from 'app/core/selectors/navModel'; -import { StoreState } from 'app/types'; - -import { GrafanaRouteComponentProps } from '../../core/navigation/types'; import { SnapshotListTable } from './components/SnapshotListTable'; -interface ConnectedProps { - navModel: NavModel; -} -interface Props extends ConnectedProps, GrafanaRouteComponentProps {} - -export const SnapshotListPage: FC = ({ navModel, location }) => { +export const SnapshotListPage = ({}) => { return ( - + @@ -25,8 +14,4 @@ export const SnapshotListPage: FC = ({ navModel, location }) => { ); }; -const mapStateToProps: MapStateToProps = (state: StoreState) => ({ - navModel: getNavModel(state.navIndex, 'snapshots'), -}); - -export default connect(mapStateToProps)(SnapshotListPage); +export default SnapshotListPage; diff --git a/public/app/features/playlist/PlaylistEditPage.test.tsx b/public/app/features/playlist/PlaylistEditPage.test.tsx index eedba69fa60..3a859580188 100644 --- a/public/app/features/playlist/PlaylistEditPage.test.tsx +++ b/public/app/features/playlist/PlaylistEditPage.test.tsx @@ -27,10 +27,6 @@ async function getTestContext({ name, interval, items, uid }: Partial const match: any = { params: { uid: 'foo' } }; const location: any = {}; const history: any = {}; - const navModel: any = { - node: {}, - main: {}, - }; const getMock = jest.spyOn(backendSrv, 'get'); const putMock = jest.spyOn(backendSrv, 'put'); getMock.mockResolvedValue({ @@ -40,14 +36,7 @@ async function getTestContext({ name, interval, items, uid }: Partial uid: 'foo', }); const { rerender } = render( - + ); await waitFor(() => expect(getMock).toHaveBeenCalledTimes(1)); diff --git a/public/app/features/playlist/PlaylistEditPage.tsx b/public/app/features/playlist/PlaylistEditPage.tsx index 24eb413ef12..c42502d65ab 100644 --- a/public/app/features/playlist/PlaylistEditPage.tsx +++ b/public/app/features/playlist/PlaylistEditPage.tsx @@ -1,12 +1,8 @@ import React, { FC } from 'react'; -import { connect, MapStateToProps } from 'react-redux'; -import { NavModel } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; -import { getNavModel } from 'app/core/selectors/navModel'; -import { StoreState } from 'app/types'; import { GrafanaRouteComponentProps } from '../../core/navigation/types'; @@ -16,17 +12,13 @@ import { getPlaylistStyles } from './styles'; import { Playlist } from './types'; import { usePlaylist } from './usePlaylist'; -interface ConnectedProps { - navModel: NavModel; -} - export interface RouteParams { uid: string; } -interface Props extends ConnectedProps, GrafanaRouteComponentProps {} +interface Props extends GrafanaRouteComponentProps {} -export const PlaylistEditPage: FC = ({ navModel, match }) => { +export const PlaylistEditPage: FC = ({ match }) => { const styles = useStyles2(getPlaylistStyles); const { playlist, loading } = usePlaylist(match.params.uid); const onSubmit = async (playlist: Playlist) => { @@ -35,7 +27,7 @@ export const PlaylistEditPage: FC = ({ navModel, match }) => { }; return ( - +

Edit playlist

@@ -50,8 +42,4 @@ export const PlaylistEditPage: FC = ({ navModel, match }) => { ); }; -const mapStateToProps: MapStateToProps = (state: StoreState) => ({ - navModel: getNavModel(state.navIndex, 'playlists'), -}); - -export default connect(mapStateToProps)(PlaylistEditPage); +export default PlaylistEditPage; diff --git a/public/app/features/playlist/PlaylistForm.tsx b/public/app/features/playlist/PlaylistForm.tsx index fd06e560c63..1d70ca5fac9 100644 --- a/public/app/features/playlist/PlaylistForm.tsx +++ b/public/app/features/playlist/PlaylistForm.tsx @@ -23,7 +23,7 @@ export const PlaylistForm: FC = ({ onSubmit, playlist }) => { const { name, interval, items: propItems } = playlist; const { items, addById, addByTag, deleteItem, moveDown, moveUp } = usePlaylistItems(propItems); return ( - <> +
onSubmit({ ...list, items })} validateOn={'onBlur'}> {({ register, errors }) => { const isDisabled = items.length === 0 || Object.keys(errors).length > 0; @@ -81,6 +81,6 @@ export const PlaylistForm: FC = ({ onSubmit, playlist }) => { ); }} - +
); }; diff --git a/public/app/features/playlist/PlaylistNewPage.test.tsx b/public/app/features/playlist/PlaylistNewPage.test.tsx index d70476bf5c8..9b4285e4277 100644 --- a/public/app/features/playlist/PlaylistNewPage.test.tsx +++ b/public/app/features/playlist/PlaylistNewPage.test.tsx @@ -30,26 +30,9 @@ jest.mock('../../core/components/TagFilter/TagFilter', () => ({ function getTestContext({ name, interval, items }: Partial = {}) { jest.clearAllMocks(); const playlist = { name, items, interval } as unknown as Playlist; - const queryParams = {}; - const route: any = {}; - const match: any = {}; - const location: any = {}; - const history: any = {}; - const navModel: any = { - node: {}, - main: {}, - }; const backendSrvMock = jest.spyOn(backendSrv, 'post'); - const { rerender } = render( - - ); + + const { rerender } = render(); return { playlist, rerender, backendSrvMock }; } diff --git a/public/app/features/playlist/PlaylistNewPage.tsx b/public/app/features/playlist/PlaylistNewPage.tsx index e7ef84960b8..579f0d83466 100644 --- a/public/app/features/playlist/PlaylistNewPage.tsx +++ b/public/app/features/playlist/PlaylistNewPage.tsx @@ -1,14 +1,8 @@ -import React, { FC } from 'react'; -import { connect, MapStateToProps } from 'react-redux'; +import React from 'react'; -import { NavModel } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { useStyles2 } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; -import { getNavModel } from 'app/core/selectors/navModel'; -import { StoreState } from 'app/types'; - -import { GrafanaRouteComponentProps } from '../../core/navigation/types'; import { PlaylistForm } from './PlaylistForm'; import { createPlaylist } from './api'; @@ -16,13 +10,7 @@ import { getPlaylistStyles } from './styles'; import { Playlist } from './types'; import { usePlaylist } from './usePlaylist'; -interface ConnectedProps { - navModel: NavModel; -} - -interface Props extends ConnectedProps, GrafanaRouteComponentProps {} - -export const PlaylistNewPage: FC = ({ navModel }) => { +export const PlaylistNewPage = () => { const styles = useStyles2(getPlaylistStyles); const { playlist, loading } = usePlaylist(); const onSubmit = async (playlist: Playlist) => { @@ -31,7 +19,7 @@ export const PlaylistNewPage: FC = ({ navModel }) => { }; return ( - +

New Playlist

@@ -46,8 +34,4 @@ export const PlaylistNewPage: FC = ({ navModel }) => { ); }; -const mapStateToProps: MapStateToProps = (state: StoreState) => ({ - navModel: getNavModel(state.navIndex, 'playlists'), -}); - -export default connect(mapStateToProps)(PlaylistNewPage); +export default PlaylistNewPage; diff --git a/public/app/features/playlist/PlaylistPage.test.tsx b/public/app/features/playlist/PlaylistPage.test.tsx index 53d9a6aa57e..59aa7e6f60c 100644 --- a/public/app/features/playlist/PlaylistPage.test.tsx +++ b/public/app/features/playlist/PlaylistPage.test.tsx @@ -3,9 +3,7 @@ import React from 'react'; import { contextSrv } from 'app/core/services/context_srv'; -import { locationService } from '../../../../packages/grafana-runtime/src'; - -import { PlaylistPage, PlaylistPageProps } from './PlaylistPage'; +import { PlaylistPage } from './PlaylistPage'; const fnMock = jest.fn(); @@ -22,29 +20,8 @@ jest.mock('app/core/services/context_srv', () => ({ }, })); -function getTestContext(propOverrides?: object) { - const props: PlaylistPageProps = { - navModel: { - main: { - text: 'Playlist', - }, - node: { - text: 'playlist', - }, - }, - route: { - path: '/playlists', - component: jest.fn(), - }, - queryParams: { state: 'ok' }, - match: { params: { name: 'playlist', sourceName: 'test playlist' }, isExact: false, url: 'asdf', path: '' }, - history: locationService.getHistory(), - location: { pathname: '', hash: '', search: '', state: '' }, - }; - - Object.assign(props, propOverrides); - - return render(); +function getTestContext() { + return render(); } describe('PlaylistPage', () => { diff --git a/public/app/features/playlist/PlaylistPage.tsx b/public/app/features/playlist/PlaylistPage.tsx index e8a997f0232..c32bdaec989 100644 --- a/public/app/features/playlist/PlaylistPage.tsx +++ b/public/app/features/playlist/PlaylistPage.tsx @@ -1,17 +1,12 @@ -import React, { FC, useState } from 'react'; -import { connect, MapStateToProps } from 'react-redux'; +import React, { useState } from 'react'; import { useDebounce } from 'react-use'; -import { NavModel } from '@grafana/data'; import { ConfirmModal } from '@grafana/ui'; import { Page } from 'app/core/components/Page/Page'; import PageActionBar from 'app/core/components/PageActionBar/PageActionBar'; -import { getNavModel } from 'app/core/selectors/navModel'; import { contextSrv } from 'app/core/services/context_srv'; -import { StoreState } from 'app/types'; import EmptyListCTA from '../../core/components/EmptyListCTA/EmptyListCTA'; -import { GrafanaRouteComponentProps } from '../../core/navigation/types'; import { EmptyQueryListBanner } from './EmptyQueryListBanner'; import { PlaylistPageList } from './PlaylistPageList'; @@ -19,12 +14,7 @@ import { StartModal } from './StartModal'; import { deletePlaylist, getAllPlaylist } from './api'; import { PlaylistDTO } from './types'; -interface ConnectedProps { - navModel: NavModel; -} -export interface PlaylistPageProps extends ConnectedProps, GrafanaRouteComponentProps {} - -export const PlaylistPage: FC = ({ navModel }) => { +export const PlaylistPage = () => { const [searchQuery, setSearchQuery] = useState(''); const [debouncedSearchQuery, setDebouncedSearchQuery] = useState(searchQuery); const [hasFetched, setHasFetched] = useState(false); @@ -76,7 +66,7 @@ export const PlaylistPage: FC = ({ navModel }) => { const showSearch = playlists.length > 0 || searchQuery.length > 0 || debouncedSearchQuery.length > 0; return ( - + {showSearch && ( = ({ navModel }) => { ); }; -const mapStateToProps: MapStateToProps = (state: StoreState) => ({ - navModel: getNavModel(state.navIndex, 'playlists'), -}); - -export default connect(mapStateToProps)(PlaylistPage); +export default PlaylistPage; diff --git a/public/app/features/search/components/DashboardListPage.tsx b/public/app/features/search/components/DashboardListPage.tsx index bbb5b34bd17..33e0ba97a35 100644 --- a/public/app/features/search/components/DashboardListPage.tsx +++ b/public/app/features/search/components/DashboardListPage.tsx @@ -1,13 +1,11 @@ import { css } from '@emotion/css'; import React, { FC, memo } from 'react'; -import { connect, MapStateToProps } from 'react-redux'; import { useAsync } from 'react-use'; -import { NavModel, locationUtil } from '@grafana/data'; +import { locationUtil, NavModelItem } from '@grafana/data'; import { locationService } from '@grafana/runtime'; import { Page } from 'app/core/components/Page/Page'; -import { getNavModel } from 'app/core/selectors/navModel'; -import { FolderDTO, StoreState } from 'app/types'; +import { FolderDTO } from 'app/types'; import { GrafanaRouteComponentProps } from '../../../core/navigation/types'; import { loadFolderPage } from '../loaders'; @@ -19,17 +17,14 @@ export interface DashboardListPageRouteParams { slug?: string; } -interface DashboardListPageConnectedProps { - navModel: NavModel; -} -interface Props extends GrafanaRouteComponentProps, DashboardListPageConnectedProps {} +interface Props extends GrafanaRouteComponentProps {} -export const DashboardListPage: FC = memo(({ navModel, match, location }) => { - const { loading, value } = useAsync<() => Promise<{ folder?: FolderDTO; pageNavModel: NavModel }>>(() => { +export const DashboardListPage: FC = memo(({ match, location }) => { + const { loading, value } = useAsync<() => Promise<{ folder?: FolderDTO; pageNav?: NavModelItem }>>(() => { const uid = match.params.uid; const url = location.pathname; if (!uid || !url.startsWith('/dashboards')) { - return Promise.resolve({ pageNavModel: navModel }); + return Promise.resolve({}); } return loadFolderPage(uid!).then(({ folder, folderNav }) => { @@ -39,12 +34,12 @@ export const DashboardListPage: FC = memo(({ navModel, match, location }) locationService.push(path); } - return { folder, pageNavModel: { ...navModel, main: folderNav } }; + return { folder, pageNav: folderNav }; }); }, [match.params.uid]); return ( - + = memo(({ navModel, match, location }) DashboardListPage.displayName = 'DashboardListPage'; -const mapStateToProps: MapStateToProps = (state) => { - return { - navModel: getNavModel(state.navIndex, 'manage-dashboards'), - }; -}; - -export default connect(mapStateToProps)(DashboardListPage); +export default DashboardListPage; diff --git a/public/app/routes/routes.tsx b/public/app/routes/routes.tsx index 311668b10d4..bb9eece76b7 100644 --- a/public/app/routes/routes.tsx +++ b/public/app/routes/routes.tsx @@ -51,8 +51,6 @@ export function getAppRoutes(): RouteDescriptor[] { path: '/dashboard/new', pageClass: 'page-dashboard', routeName: DashboardRoutes.New, - // TODO[Router] - //roles: () => (contextSrv.hasEditPermissionInFolders ? [contextSrv.user.orgRole] : ['Admin']), component: SafeDynamicImport( () => import(/* webpackChunkName: "DashboardPage" */ '../features/dashboard/containers/DashboardPage') ), @@ -61,6 +59,7 @@ export function getAppRoutes(): RouteDescriptor[] { path: '/d-solo/:uid/:slug', pageClass: 'dashboard-solo', routeName: DashboardRoutes.Normal, + chromeless: true, component: SafeDynamicImport( () => import(/* webpackChunkName: "SoloPanelPage" */ '../features/dashboard/containers/SoloPanelPage') ), @@ -70,6 +69,7 @@ export function getAppRoutes(): RouteDescriptor[] { path: '/dashboard-solo/:type/:slug', pageClass: 'dashboard-solo', routeName: DashboardRoutes.Normal, + chromeless: true, component: SafeDynamicImport( () => import(/* webpackChunkName: "SoloPanelPage" */ '../features/dashboard/containers/SoloPanelPage') ), @@ -78,6 +78,7 @@ export function getAppRoutes(): RouteDescriptor[] { path: '/d-solo/:uid', pageClass: 'dashboard-solo', routeName: DashboardRoutes.Normal, + chromeless: true, component: SafeDynamicImport( () => import(/* webpackChunkName: "SoloPanelPage" */ '../features/dashboard/containers/SoloPanelPage') ),