mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
FolderPage: Improve folder page to work with new nav breadcrumbs and modify Dashboard page show path based breadcrumbs" (#52428)
* FolderPage: Progress on folder page navigation * Dashboard to adapt breadcrumbs when opening dashboard from file storage * add warning when topnav is not enabled Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
parent
79d92aa03e
commit
b29045b57b
@ -12,9 +12,10 @@ import { PageLayoutType } from 'app/core/components/Page/types';
|
||||
import { createErrorNotification } from 'app/core/copy/appNotification';
|
||||
import { getKioskMode } from 'app/core/navigation/kiosk';
|
||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||
import { PanelModel } from 'app/features/dashboard/state';
|
||||
import { DashboardModel, PanelModel } from 'app/features/dashboard/state';
|
||||
import { dashboardWatcher } from 'app/features/live/dashboard/dashboardWatcher';
|
||||
import { KioskMode, StoreState } from 'app/types';
|
||||
import { getPageNavFromSlug, getRootContentNavModel } from 'app/features/storage/StorageFolderPage';
|
||||
import { DashboardRoutes, KioskMode, StoreState } from 'app/types';
|
||||
import { PanelEditEnteredEvent, PanelEditExitedEvent } from 'app/types/events';
|
||||
|
||||
import { cancelVariables, templateVarsChangedInUrl } from '../../variables/state/actions';
|
||||
@ -149,28 +150,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
||||
return;
|
||||
}
|
||||
|
||||
// Update page nav
|
||||
if (!this.pageNav || dashboard.title !== this.pageNav.text) {
|
||||
this.pageNav = {
|
||||
text: dashboard.title,
|
||||
url: locationUtil.getUrlForPartial(this.props.history.location, {
|
||||
editview: null,
|
||||
editPanel: null,
|
||||
viewPanel: null,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
// Check if folder changed
|
||||
if (
|
||||
dashboard.meta.folderTitle &&
|
||||
(!this.pageNav.parentItem || this.pageNav.parentItem.text !== dashboard.meta.folderTitle)
|
||||
) {
|
||||
this.pageNav.parentItem = {
|
||||
text: dashboard.meta.folderTitle,
|
||||
url: `/dashboards/f/${dashboard.meta.folderUid}`,
|
||||
};
|
||||
}
|
||||
this.updatePageNav(dashboard);
|
||||
|
||||
if (
|
||||
prevProps.match.params.uid !== match.params.uid ||
|
||||
@ -339,6 +319,45 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
||||
return inspectPanel;
|
||||
}
|
||||
|
||||
updatePageNav(dashboard: DashboardModel) {
|
||||
if (!this.pageNav || dashboard.title !== this.pageNav.text) {
|
||||
this.pageNav = {
|
||||
text: dashboard.title,
|
||||
url: locationUtil.getUrlForPartial(this.props.history.location, {
|
||||
editview: null,
|
||||
editPanel: null,
|
||||
viewPanel: null,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
// Check if folder changed
|
||||
if (
|
||||
dashboard.meta.folderTitle &&
|
||||
(!this.pageNav.parentItem || this.pageNav.parentItem.text !== dashboard.meta.folderTitle)
|
||||
) {
|
||||
this.pageNav.parentItem = {
|
||||
text: dashboard.meta.folderTitle,
|
||||
url: `/dashboards/f/${dashboard.meta.folderUid}`,
|
||||
};
|
||||
}
|
||||
|
||||
if (this.props.route.routeName === DashboardRoutes.Path) {
|
||||
const pageNav = getPageNavFromSlug(this.props.match.params.slug!);
|
||||
if (pageNav?.parentItem) {
|
||||
this.pageNav.parentItem = pageNav.parentItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getPageProps() {
|
||||
if (this.props.route.routeName === DashboardRoutes.Path) {
|
||||
return { navModel: getRootContentNavModel(), pageNav: this.pageNav };
|
||||
} else {
|
||||
return { navId: 'dashboards', pageNav: this.pageNav };
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const { dashboard, initError, queryParams, isPublic } = this.props;
|
||||
const { editPanel, viewPanel, updateScrollTop } = this.state;
|
||||
@ -368,8 +387,7 @@ export class UnthemedDashboardPage extends PureComponent<Props, State> {
|
||||
|
||||
return (
|
||||
<Page
|
||||
navId="dashboards"
|
||||
pageNav={this.pageNav}
|
||||
{...this.getPageProps()}
|
||||
layout={PageLayoutType.Dashboard}
|
||||
toolbar={toolbar}
|
||||
className={containerClassNames}
|
||||
|
@ -1,32 +1,24 @@
|
||||
import { css } from '@emotion/css';
|
||||
import React, { FC } from 'react';
|
||||
import React from 'react';
|
||||
import { useAsync } from 'react-use';
|
||||
|
||||
import { DataFrame, GrafanaTheme2 } from '@grafana/data';
|
||||
import { Card, Icon, Spinner, useStyles2 } from '@grafana/ui';
|
||||
import { DataFrame, NavModel, NavModelItem } from '@grafana/data';
|
||||
import { config } from '@grafana/runtime';
|
||||
import { Alert, Card, Icon, Spinner } from '@grafana/ui';
|
||||
import { Page } from 'app/core/components/Page/Page';
|
||||
import { GrafanaRouteComponentProps } from 'app/core/navigation/types';
|
||||
|
||||
import { getGrafanaStorage } from './storage';
|
||||
|
||||
export interface Props extends GrafanaRouteComponentProps<{ slug: string }> {}
|
||||
|
||||
export const StorageFolderPage: FC<Props> = (props) => {
|
||||
const slug = props.match.params.slug;
|
||||
|
||||
const styles = useStyles2(getStyles);
|
||||
export function StorageFolderPage(props: Props) {
|
||||
const slug = props.match.params.slug ?? '';
|
||||
const listing = useAsync((): Promise<DataFrame | undefined> => {
|
||||
return getGrafanaStorage().list(slug);
|
||||
}, [slug]);
|
||||
|
||||
let base = document.location.pathname;
|
||||
if (!base.endsWith('/')) {
|
||||
base += '/';
|
||||
}
|
||||
let parent = '';
|
||||
const idx = base.lastIndexOf('/', base.length - 2);
|
||||
if (idx > 0) {
|
||||
parent = base.substring(0, idx);
|
||||
}
|
||||
const childRoot = slug.length > 0 ? `g/${slug}/` : 'g/';
|
||||
const pageNav = getPageNavFromSlug(slug);
|
||||
|
||||
const renderListing = () => {
|
||||
if (listing.value) {
|
||||
@ -35,8 +27,10 @@ export const StorageFolderPage: FC<Props> = (props) => {
|
||||
let name = item;
|
||||
const isFolder = name.indexOf('.') < 0;
|
||||
const isDash = !isFolder && name.endsWith('.json');
|
||||
const url = `${childRoot}${name}`;
|
||||
|
||||
return (
|
||||
<Card key={name} href={isFolder || isDash ? base + name : undefined}>
|
||||
<Card key={name} href={isFolder || isDash ? url : undefined}>
|
||||
<Card.Heading>{name}</Card.Heading>
|
||||
<Card.Figure>
|
||||
<Icon name={isFolder ? 'folder' : isDash ? 'gf-grid' : 'file-alt'} size="sm" />
|
||||
@ -51,29 +45,37 @@ export const StorageFolderPage: FC<Props> = (props) => {
|
||||
return <div>?</div>;
|
||||
};
|
||||
|
||||
const navModel = getRootContentNavModel();
|
||||
|
||||
return (
|
||||
<div className={styles.wrapper}>
|
||||
{slug?.length > 0 && (
|
||||
<>
|
||||
<h1>{slug}</h1>
|
||||
<Card href={parent}>
|
||||
<Card.Heading>{parent}</Card.Heading>
|
||||
<Card.Figure>
|
||||
<Icon name="arrow-left" size="sm" />
|
||||
</Card.Figure>
|
||||
</Card>
|
||||
<br />
|
||||
</>
|
||||
<Page navModel={navModel} pageNav={pageNav}>
|
||||
{!config.featureToggles.topnav && (
|
||||
<div>
|
||||
<Alert title="Enable the topnav feature toggle">This page is designed assuming topnav is enabled</Alert>
|
||||
</div>
|
||||
)}
|
||||
{renderListing()}
|
||||
</div>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
wrapper: css`
|
||||
margin: 50px;
|
||||
`,
|
||||
});
|
||||
export function getPageNavFromSlug(slug: string) {
|
||||
const parts = slug.split('/');
|
||||
let pageNavs: NavModelItem[] = [];
|
||||
let url = 'g';
|
||||
let lastPageNav: NavModelItem | undefined;
|
||||
|
||||
for (let i = 0; i < parts.length; i++) {
|
||||
url += `/${parts[i]}`;
|
||||
pageNavs.push({ text: parts[i], url, parentItem: lastPageNav });
|
||||
lastPageNav = pageNavs[pageNavs.length - 1];
|
||||
}
|
||||
|
||||
return lastPageNav;
|
||||
}
|
||||
|
||||
export function getRootContentNavModel(): NavModel {
|
||||
return { main: { text: 'C:' }, node: { text: 'Content', url: '/g' } };
|
||||
}
|
||||
|
||||
export default StorageFolderPage;
|
||||
|
@ -123,6 +123,7 @@ class SimpleStorage implements GrafanaStorage {
|
||||
if (!path.endsWith('.json')) {
|
||||
path += '.json';
|
||||
}
|
||||
|
||||
const result = await backendSrv.get(`/api/storage/read/${path}`);
|
||||
result.uid = path;
|
||||
delete result.id; // Saved with the dev dashboards!
|
||||
|
Loading…
Reference in New Issue
Block a user