mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Fixed lots of loading flow issues and updated solo route page
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import config from 'app/core/config';
|
||||
|
||||
export const stripBaseFromUrl = url => {
|
||||
export const stripBaseFromUrl = (url: string): string => {
|
||||
const appSubUrl = config.appSubUrl;
|
||||
const stripExtraChars = appSubUrl.endsWith('/') ? 1 : 0;
|
||||
const urlWithoutBase =
|
||||
|
||||
@@ -5,6 +5,7 @@ import { connect } from 'react-redux';
|
||||
// Utils & Services
|
||||
import { AngularComponent, getAngularLoader } from 'app/core/services/AngularLoader';
|
||||
import { appEvents } from 'app/core/app_events';
|
||||
import { PlaylistSrv } from 'app/features/playlist/playlist_srv';
|
||||
|
||||
// Components
|
||||
import { DashNavButton } from './DashNavButton';
|
||||
@@ -116,12 +117,13 @@ export class DashNav extends PureComponent<Props> {
|
||||
};
|
||||
|
||||
render() {
|
||||
const { dashboard, isFullscreen, editview } = this.props;
|
||||
const { dashboard, isFullscreen, editview, $injector } = this.props;
|
||||
const { canStar, canSave, canShare, folderTitle, showSettings, isStarred } = dashboard.meta;
|
||||
const { snapshot } = dashboard;
|
||||
|
||||
const haveFolder = dashboard.meta.folderId > 0;
|
||||
const snapshotUrl = snapshot && snapshot.originalUrl;
|
||||
const playlistSrv: PlaylistSrv = $injector.get('playlistSrv');
|
||||
|
||||
return (
|
||||
<div className="navbar">
|
||||
@@ -135,13 +137,29 @@ export class DashNav extends PureComponent<Props> {
|
||||
</div>
|
||||
|
||||
<div className="navbar__spacer" />
|
||||
{/*
|
||||
<div class="navbar-buttons navbar-buttons--playlist" ng-if="ctrl.playlistSrv.isPlaying">
|
||||
<a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.prev()"><i class="fa fa-step-backward"></i></a>
|
||||
<a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.stop()"><i class="fa fa-stop"></i></a>
|
||||
<a class="navbar-button navbar-button--tight" ng-click="ctrl.playlistSrv.next()"><i class="fa fa-step-forward"></i></a>
|
||||
</div>
|
||||
*/}
|
||||
|
||||
{playlistSrv.isPlaying && (
|
||||
<div className="navbar-buttons navbar-buttons--playlist">
|
||||
<DashNavButton
|
||||
tooltip="Jump to previous dashboard"
|
||||
classSuffix="tight"
|
||||
icon="fa fa-step-backward"
|
||||
onClick={() => playlistSrv.prev()}
|
||||
/>
|
||||
<DashNavButton
|
||||
tooltip="Stop playlist"
|
||||
classSuffix="tight"
|
||||
icon="fa fa-stop"
|
||||
onClick={() => playlistSrv.stop()}
|
||||
/>
|
||||
<DashNavButton
|
||||
tooltip="Jump forward"
|
||||
classSuffix="tight"
|
||||
icon="fa fa-forward"
|
||||
onClick={() => playlistSrv.next()}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="navbar-buttons navbar-buttons--actions">
|
||||
{canSave && (
|
||||
@@ -151,71 +169,71 @@ export class DashNav extends PureComponent<Props> {
|
||||
icon="gicon gicon-add-panel"
|
||||
onClick={this.onAddPanel}
|
||||
/>
|
||||
)}
|
||||
)}
|
||||
|
||||
{canStar && (
|
||||
<DashNavButton
|
||||
tooltip="Mark as favorite"
|
||||
classSuffix="star"
|
||||
icon={`${isStarred ? 'fa fa-star' : 'fa fa-star-o'}`}
|
||||
onClick={this.onStarDashboard}
|
||||
/>
|
||||
)}
|
||||
{canStar && (
|
||||
<DashNavButton
|
||||
tooltip="Mark as favorite"
|
||||
classSuffix="star"
|
||||
icon={`${isStarred ? 'fa fa-star' : 'fa fa-star-o'}`}
|
||||
onClick={this.onStarDashboard}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canShare && (
|
||||
<DashNavButton
|
||||
tooltip="Share dashboard"
|
||||
classSuffix="share"
|
||||
icon="fa fa-share-square-o"
|
||||
onClick={this.onOpenShare}
|
||||
/>
|
||||
)}
|
||||
{canShare && (
|
||||
<DashNavButton
|
||||
tooltip="Share dashboard"
|
||||
classSuffix="share"
|
||||
icon="fa fa-share-square-o"
|
||||
onClick={this.onOpenShare}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canSave && (
|
||||
<DashNavButton tooltip="Save dashboard" classSuffix="save" icon="fa fa-save" onClick={this.onSave} />
|
||||
)}
|
||||
{canSave && (
|
||||
<DashNavButton tooltip="Save dashboard" classSuffix="save" icon="fa fa-save" onClick={this.onSave} />
|
||||
)}
|
||||
|
||||
{snapshotUrl && (
|
||||
<DashNavButton
|
||||
tooltip="Open original dashboard"
|
||||
classSuffix="snapshot-origin"
|
||||
icon="fa fa-link"
|
||||
href={snapshotUrl}
|
||||
/>
|
||||
)}
|
||||
{snapshotUrl && (
|
||||
<DashNavButton
|
||||
tooltip="Open original dashboard"
|
||||
classSuffix="snapshot-origin"
|
||||
icon="fa fa-link"
|
||||
href={snapshotUrl}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showSettings && (
|
||||
<DashNavButton
|
||||
tooltip="Dashboard settings"
|
||||
classSuffix="settings"
|
||||
icon="fa fa-cog"
|
||||
onClick={this.onOpenSettings}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
{showSettings && (
|
||||
<DashNavButton
|
||||
tooltip="Dashboard settings"
|
||||
classSuffix="settings"
|
||||
icon="fa fa-cog"
|
||||
onClick={this.onOpenSettings}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="navbar-buttons navbar-buttons--tv">
|
||||
<DashNavButton
|
||||
tooltip="Cycke view mode"
|
||||
classSuffix="tv"
|
||||
icon="fa fa-desktop"
|
||||
onClick={this.onToggleTVMode}
|
||||
/>
|
||||
</div>
|
||||
<div className="navbar-buttons navbar-buttons--tv">
|
||||
<DashNavButton
|
||||
tooltip="Cycke view mode"
|
||||
classSuffix="tv"
|
||||
icon="fa fa-desktop"
|
||||
onClick={this.onToggleTVMode}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="gf-timepicker-nav" ref={element => (this.timePickerEl = element)} />
|
||||
<div className="gf-timepicker-nav" ref={element => (this.timePickerEl = element)} />
|
||||
|
||||
{(isFullscreen || editview) && (
|
||||
<div className="navbar-buttons navbar-buttons--close">
|
||||
<DashNavButton
|
||||
tooltip="Back to dashboard"
|
||||
classSuffix="primary"
|
||||
icon="fa fa-reply"
|
||||
onClick={this.onClose}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{(isFullscreen || editview) && (
|
||||
<div className="navbar-buttons navbar-buttons--close">
|
||||
<DashNavButton
|
||||
tooltip="Back to dashboard"
|
||||
classSuffix="primary"
|
||||
icon="fa fa-reply"
|
||||
onClick={this.onClose}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,6 +69,7 @@ export class DashboardPage extends PureComponent<Props, State> {
|
||||
urlType: this.props.urlType,
|
||||
urlFolderId: this.props.urlFolderId,
|
||||
routeInfo: this.props.routeInfo,
|
||||
fixUrl: true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3,98 +3,78 @@ import React, { Component } from 'react';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
// Utils & Services
|
||||
import appEvents from 'app/core/app_events';
|
||||
import locationUtil from 'app/core/utils/location_util';
|
||||
import { getBackendSrv } from 'app/core/services/backend_srv';
|
||||
|
||||
// Components
|
||||
import { DashboardPanel } from '../dashgrid/DashboardPanel';
|
||||
|
||||
// Redux
|
||||
import { updateLocation } from 'app/core/actions';
|
||||
import { initDashboard } from '../state/initDashboard';
|
||||
|
||||
// Types
|
||||
import { StoreState } from 'app/types';
|
||||
import { StoreState, DashboardRouteInfo } from 'app/types';
|
||||
import { PanelModel, DashboardModel } from 'app/features/dashboard/state';
|
||||
|
||||
interface Props {
|
||||
panelId: string;
|
||||
urlPanelId: string;
|
||||
urlUid?: string;
|
||||
urlSlug?: string;
|
||||
urlType?: string;
|
||||
$scope: any;
|
||||
$injector: any;
|
||||
updateLocation: typeof updateLocation;
|
||||
routeInfo: DashboardRouteInfo;
|
||||
initDashboard: typeof initDashboard;
|
||||
dashboard: DashboardModel | null;
|
||||
}
|
||||
|
||||
interface State {
|
||||
panel: PanelModel | null;
|
||||
dashboard: DashboardModel | null;
|
||||
notFound: boolean;
|
||||
}
|
||||
|
||||
export class SoloPanelPage extends Component<Props, State> {
|
||||
|
||||
state: State = {
|
||||
panel: null,
|
||||
dashboard: null,
|
||||
notFound: false,
|
||||
};
|
||||
|
||||
componentDidMount() {
|
||||
const { $injector, $scope, urlUid, urlType, urlSlug } = this.props;
|
||||
const { $injector, $scope, urlUid, urlType, urlSlug, routeInfo } = this.props;
|
||||
|
||||
// handle old urls with no uid
|
||||
if (!urlUid && !(urlType === 'script' || urlType === 'snapshot')) {
|
||||
this.redirectToNewUrl();
|
||||
return;
|
||||
}
|
||||
|
||||
const dashboardLoaderSrv = $injector.get('dashboardLoaderSrv');
|
||||
|
||||
// subscribe to event to know when dashboard controller is done with inititalization
|
||||
appEvents.on('dashboard-initialized', this.onDashoardInitialized);
|
||||
|
||||
dashboardLoaderSrv.loadDashboard(urlType, urlSlug, urlUid).then(result => {
|
||||
result.meta.soloMode = true;
|
||||
$scope.initDashboard(result, $scope);
|
||||
this.props.initDashboard({
|
||||
$injector: $injector,
|
||||
$scope: $scope,
|
||||
urlSlug: urlSlug,
|
||||
urlUid: urlUid,
|
||||
urlType: urlType,
|
||||
routeInfo: routeInfo,
|
||||
fixUrl: false,
|
||||
});
|
||||
}
|
||||
|
||||
redirectToNewUrl() {
|
||||
getBackendSrv().getDashboardBySlug(this.props.urlSlug).then(res => {
|
||||
if (res) {
|
||||
const url = locationUtil.stripBaseFromUrl(res.meta.url.replace('/d/', '/d-solo/'));
|
||||
this.props.updateLocation(url);
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
const { urlPanelId, dashboard } = this.props;
|
||||
|
||||
if (!dashboard) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we just got the dashboard!
|
||||
if (!prevProps.dashboard) {
|
||||
const panel = dashboard.getPanelById(parseInt(urlPanelId, 10));
|
||||
if (!panel) {
|
||||
this.setState({ notFound: true });
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onDashoardInitialized = () => {
|
||||
const { $scope, panelId } = this.props;
|
||||
|
||||
const dashboard: DashboardModel = $scope.dashboard;
|
||||
const panel = dashboard.getPanelById(parseInt(panelId, 10));
|
||||
|
||||
if (!panel) {
|
||||
this.setState({ notFound: true });
|
||||
return;
|
||||
this.setState({ panel });
|
||||
}
|
||||
|
||||
this.setState({ dashboard, panel });
|
||||
};
|
||||
}
|
||||
|
||||
render() {
|
||||
const { panelId } = this.props;
|
||||
const { notFound, panel, dashboard } = this.state;
|
||||
const { urlPanelId, dashboard } = this.props;
|
||||
const { notFound, panel } = this.state;
|
||||
|
||||
if (notFound) {
|
||||
return (
|
||||
<div className="alert alert-error">
|
||||
Panel with id { panelId } not found
|
||||
</div>
|
||||
);
|
||||
return <div className="alert alert-error">Panel with id {urlPanelId} not found</div>;
|
||||
}
|
||||
|
||||
if (!panel) {
|
||||
@@ -113,11 +93,13 @@ const mapStateToProps = (state: StoreState) => ({
|
||||
urlUid: state.location.routeParams.uid,
|
||||
urlSlug: state.location.routeParams.slug,
|
||||
urlType: state.location.routeParams.type,
|
||||
panelId: state.location.query.panelId
|
||||
urlPanelId: state.location.query.panelId,
|
||||
loadingState: state.dashboard.loadingState,
|
||||
dashboard: state.dashboard.model as DashboardModel,
|
||||
});
|
||||
|
||||
const mapDispatchToProps = {
|
||||
updateLocation
|
||||
initDashboard,
|
||||
};
|
||||
|
||||
export default hot(module)(connect(mapStateToProps, mapDispatchToProps)(SoloPanelPage));
|
||||
|
||||
@@ -8,7 +8,6 @@ export class DashboardSrv {
|
||||
|
||||
/** @ngInject */
|
||||
constructor(private backendSrv, private $rootScope, private $location) {
|
||||
appEvents.on('save-dashboard', this.saveDashboard.bind(this), $rootScope);
|
||||
appEvents.on('save-dashboard', this.saveDashboard.bind(this), $rootScope);
|
||||
appEvents.on('panel-change-view', this.onPanelChangeView);
|
||||
}
|
||||
|
||||
@@ -25,16 +25,24 @@ export interface InitDashboardArgs {
|
||||
urlUid?: string;
|
||||
urlSlug?: string;
|
||||
urlType?: string;
|
||||
urlFolderId: string;
|
||||
urlFolderId?: string;
|
||||
routeInfo: string;
|
||||
fixUrl: boolean;
|
||||
}
|
||||
|
||||
async function redirectToNewUrl(slug: string, dispatch: any) {
|
||||
async function redirectToNewUrl(slug: string, dispatch: any, currentPath: string) {
|
||||
const res = await getBackendSrv().getDashboardBySlug(slug);
|
||||
|
||||
if (res) {
|
||||
const url = locationUtil.stripBaseFromUrl(res.meta.url.replace('/d/', '/d-solo/'));
|
||||
dispatch(updateLocation(url));
|
||||
let newUrl = res.meta.url;
|
||||
|
||||
// fix solo route urls
|
||||
if (currentPath.indexOf('dashboard-solo') !== -1) {
|
||||
newUrl = newUrl.replace('/d/', '/d-solo/');
|
||||
}
|
||||
|
||||
const url = locationUtil.stripBaseFromUrl(newUrl);
|
||||
dispatch(updateLocation({ path: url, partial: true, replace: true }));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +54,7 @@ export function initDashboard({
|
||||
urlType,
|
||||
urlFolderId,
|
||||
routeInfo,
|
||||
fixUrl,
|
||||
}: InitDashboardArgs): ThunkResult<void> {
|
||||
return async (dispatch, getState) => {
|
||||
let dashDTO = null;
|
||||
@@ -76,14 +85,14 @@ export function initDashboard({
|
||||
case DashboardRouteInfo.Normal: {
|
||||
// for old db routes we redirect
|
||||
if (urlType === 'db') {
|
||||
redirectToNewUrl(urlSlug, dispatch);
|
||||
redirectToNewUrl(urlSlug, dispatch, getState().location.path);
|
||||
return;
|
||||
}
|
||||
|
||||
const loaderSrv = $injector.get('dashboardLoaderSrv');
|
||||
dashDTO = await loaderSrv.loadDashboard(urlType, urlSlug, urlUid);
|
||||
|
||||
if (dashDTO.meta.url) {
|
||||
if (fixUrl && dashDTO.meta.url) {
|
||||
// check if the current url is correct (might be old slug)
|
||||
const dashboardUrl = locationUtil.stripBaseFromUrl(dashDTO.meta.url);
|
||||
const currentPath = getState().location.path;
|
||||
|
||||
@@ -45,12 +45,6 @@ export class GrafanaCtrl {
|
||||
};
|
||||
|
||||
$rootScope.colors = colors;
|
||||
|
||||
$scope.initDashboard = (dashboardData, viewScope) => {
|
||||
$scope.appEvent('dashboard-fetch-end', dashboardData);
|
||||
$controller('DashboardCtrl', { $scope: viewScope }).init(dashboardData);
|
||||
};
|
||||
|
||||
$rootScope.onAppEvent = function(name, callback, localScope) {
|
||||
const unbind = $rootScope.$on(name, callback);
|
||||
let callerScope = this;
|
||||
|
||||
Reference in New Issue
Block a user