Commit 8574dca0 by Torkel Ödegaard

making changes suggested in review and improving typings

parent a53c3b45
...@@ -5,7 +5,7 @@ import { DashboardModel } from '../state/DashboardModel'; ...@@ -5,7 +5,7 @@ import { DashboardModel } from '../state/DashboardModel';
import { removePanel } from '../utils/panel'; import { removePanel } from '../utils/panel';
export class DashboardSrv { export class DashboardSrv {
dash: DashboardModel; dashboard: DashboardModel;
/** @ngInject */ /** @ngInject */
constructor(private backendSrv, private $rootScope, private $location) { constructor(private backendSrv, private $rootScope, private $location) {
...@@ -19,11 +19,11 @@ export class DashboardSrv { ...@@ -19,11 +19,11 @@ export class DashboardSrv {
} }
setCurrent(dashboard: DashboardModel) { setCurrent(dashboard: DashboardModel) {
this.dash = dashboard; this.dashboard = dashboard;
} }
getCurrent(): DashboardModel { getCurrent(): DashboardModel {
return this.dash; return this.dashboard;
} }
onRemovePanel = (panelId: number) => { onRemovePanel = (panelId: number) => {
...@@ -124,10 +124,10 @@ export class DashboardSrv { ...@@ -124,10 +124,10 @@ export class DashboardSrv {
} }
postSave(clone, data) { postSave(clone, data) {
this.dash.version = data.version; this.dashboard.version = data.version;
// important that these happens before location redirect below // important that these happens before location redirect below
this.$rootScope.appEvent('dashboard-saved', this.dash); this.$rootScope.appEvent('dashboard-saved', this.dashboard);
this.$rootScope.appEvent('alert-success', ['Dashboard saved']); this.$rootScope.appEvent('alert-success', ['Dashboard saved']);
const newUrl = locationUtil.stripBaseFromUrl(data.url); const newUrl = locationUtil.stripBaseFromUrl(data.url);
...@@ -137,12 +137,12 @@ export class DashboardSrv { ...@@ -137,12 +137,12 @@ export class DashboardSrv {
this.$location.url(newUrl).replace(); this.$location.url(newUrl).replace();
} }
return this.dash; return this.dashboard;
} }
save(clone, options) { save(clone, options) {
options = options || {}; options = options || {};
options.folderId = options.folderId >= 0 ? options.folderId : this.dash.meta.folderId || clone.folderId; options.folderId = options.folderId >= 0 ? options.folderId : this.dashboard.meta.folderId || clone.folderId;
return this.backendSrv return this.backendSrv
.saveDashboard(clone, options) .saveDashboard(clone, options)
...@@ -152,26 +152,26 @@ export class DashboardSrv { ...@@ -152,26 +152,26 @@ export class DashboardSrv {
saveDashboard(options?, clone?) { saveDashboard(options?, clone?) {
if (clone) { if (clone) {
this.setCurrent(this.create(clone, this.dash.meta)); this.setCurrent(this.create(clone, this.dashboard.meta));
} }
if (this.dash.meta.provisioned) { if (this.dashboard.meta.provisioned) {
return this.showDashboardProvisionedModal(); return this.showDashboardProvisionedModal();
} }
if (!this.dash.meta.canSave && options.makeEditable !== true) { if (!this.dashboard.meta.canSave && options.makeEditable !== true) {
return Promise.resolve(); return Promise.resolve();
} }
if (this.dash.title === 'New dashboard') { if (this.dashboard.title === 'New dashboard') {
return this.showSaveAsModal(); return this.showSaveAsModal();
} }
if (this.dash.version > 0) { if (this.dashboard.version > 0) {
return this.showSaveModal(); return this.showSaveModal();
} }
return this.save(this.dash.getSaveModelClone(), options); return this.save(this.dashboard.getSaveModelClone(), options);
} }
saveJSONDashboard(json: string) { saveJSONDashboard(json: string) {
...@@ -212,8 +212,8 @@ export class DashboardSrv { ...@@ -212,8 +212,8 @@ export class DashboardSrv {
} }
return promise.then(res => { return promise.then(res => {
if (this.dash && this.dash.id === dashboardId) { if (this.dashboard && this.dashboard.id === dashboardId) {
this.dash.meta.isStarred = res; this.dashboard.meta.isStarred = res;
} }
return res; return res;
}); });
......
...@@ -15,7 +15,7 @@ import sortByKeys from 'app/core/utils/sort_by_keys'; ...@@ -15,7 +15,7 @@ import sortByKeys from 'app/core/utils/sort_by_keys';
import { PanelModel } from './PanelModel'; import { PanelModel } from './PanelModel';
import { DashboardMigrator } from './DashboardMigrator'; import { DashboardMigrator } from './DashboardMigrator';
import { TimeRange } from '@grafana/ui/src'; import { TimeRange } from '@grafana/ui/src';
import { UrlQueryValue } from 'app/types'; import { UrlQueryValue, KIOSK_MODE_TV, DashboardMeta } from 'app/types';
export class DashboardModel { export class DashboardModel {
id: any; id: any;
...@@ -49,7 +49,7 @@ export class DashboardModel { ...@@ -49,7 +49,7 @@ export class DashboardModel {
// repeat process cycles // repeat process cycles
iteration: number; iteration: number;
meta: any; meta: DashboardMeta;
events: Emitter; events: Emitter;
static nonPersistedProperties: { [str: string]: boolean } = { static nonPersistedProperties: { [str: string]: boolean } = {
...@@ -887,7 +887,7 @@ export class DashboardModel { ...@@ -887,7 +887,7 @@ export class DashboardModel {
} }
// add back navbar height // add back navbar height
if (kioskMode === 'tv') { if (kioskMode === KIOSK_MODE_TV) {
visibleHeight += 55; visibleHeight += 55;
} }
......
// Libaries
import { ThunkAction } from 'redux-thunk';
// Services & Utils // Services & Utils
import { getBackendSrv } from 'app/core/services/backend_srv'; import { getBackendSrv } from 'app/core/services/backend_srv';
import { actionCreatorFactory, noPayloadActionCreatorFactory } from 'app/core/redux'; import { actionCreatorFactory, noPayloadActionCreatorFactory } from 'app/core/redux';
...@@ -11,7 +8,7 @@ import { loadPluginDashboards } from '../../plugins/state/actions'; ...@@ -11,7 +8,7 @@ import { loadPluginDashboards } from '../../plugins/state/actions';
import { notifyApp } from 'app/core/actions'; import { notifyApp } from 'app/core/actions';
// Types // Types
import { StoreState } from 'app/types'; import { ThunkResult } from 'app/types';
import { import {
DashboardAcl, DashboardAcl,
DashboardAclDTO, DashboardAclDTO,
...@@ -26,8 +23,6 @@ export const setDashboardLoadingState = actionCreatorFactory<DashboardLoadingSta ...@@ -26,8 +23,6 @@ export const setDashboardLoadingState = actionCreatorFactory<DashboardLoadingSta
export const setDashboardModel = actionCreatorFactory<MutableDashboard>('SET_DASHBOARD_MODEL').create(); export const setDashboardModel = actionCreatorFactory<MutableDashboard>('SET_DASHBOARD_MODEL').create();
export const setDashboardLoadingSlow = noPayloadActionCreatorFactory('SET_DASHBOARD_LOADING_SLOW').create(); export const setDashboardLoadingSlow = noPayloadActionCreatorFactory('SET_DASHBOARD_LOADING_SLOW').create();
export type ThunkResult<R> = ThunkAction<R, StoreState, undefined, any>;
export function getDashboardPermissions(id: number): ThunkResult<void> { export function getDashboardPermissions(id: number): ThunkResult<void> {
return async dispatch => { return async dispatch => {
const permissions = await getBackendSrv().get(`/api/dashboards/id/${id}/permissions`); const permissions = await getBackendSrv().get(`/api/dashboards/id/${id}/permissions`);
......
// Libraries
import { ThunkDispatch } from 'redux-thunk';
// Services & Utils // Services & Utils
import { createErrorNotification } from 'app/core/copy/appNotification'; import { createErrorNotification } from 'app/core/copy/appNotification';
import { getBackendSrv } from 'app/core/services/backend_srv'; import { getBackendSrv } from 'app/core/services/backend_srv';
import { DashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { DashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
import { DashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
import { TimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { AnnotationsSrv } from 'app/features/annotations/annotations_srv'; import { AnnotationsSrv } from 'app/features/annotations/annotations_srv';
import { VariableSrv } from 'app/features/templating/variable_srv'; import { VariableSrv } from 'app/features/templating/variable_srv';
...@@ -14,14 +12,19 @@ import { KeybindingSrv } from 'app/core/services/keybindingSrv'; ...@@ -14,14 +12,19 @@ import { KeybindingSrv } from 'app/core/services/keybindingSrv';
import { updateLocation } from 'app/core/actions'; import { updateLocation } from 'app/core/actions';
import { notifyApp } from 'app/core/actions'; import { notifyApp } from 'app/core/actions';
import locationUtil from 'app/core/utils/location_util'; import locationUtil from 'app/core/utils/location_util';
import { setDashboardLoadingState, ThunkResult, setDashboardModel, setDashboardLoadingSlow } from './actions'; import { setDashboardLoadingState, setDashboardModel, setDashboardLoadingSlow } from './actions';
// Types // Types
import { DashboardLoadingState, DashboardRouteInfo, StoreState } from 'app/types'; import {
DashboardLoadingState,
DashboardRouteInfo,
StoreState,
ThunkDispatch,
ThunkResult,
DashboardDTO,
} from 'app/types';
import { DashboardModel } from './DashboardModel'; import { DashboardModel } from './DashboardModel';
export type Dispatch = ThunkDispatch<StoreState, undefined, any>;
export interface InitDashboardArgs { export interface InitDashboardArgs {
$injector: any; $injector: any;
$scope: any; $scope: any;
...@@ -33,7 +36,7 @@ export interface InitDashboardArgs { ...@@ -33,7 +36,7 @@ export interface InitDashboardArgs {
fixUrl: boolean; fixUrl: boolean;
} }
async function redirectToNewUrl(slug: string, dispatch: Dispatch, currentPath: string) { async function redirectToNewUrl(slug: string, dispatch: ThunkDispatch, currentPath: string) {
const res = await getBackendSrv().getDashboardBySlug(slug); const res = await getBackendSrv().getDashboardBySlug(slug);
if (res) { if (res) {
...@@ -49,18 +52,22 @@ async function redirectToNewUrl(slug: string, dispatch: Dispatch, currentPath: s ...@@ -49,18 +52,22 @@ async function redirectToNewUrl(slug: string, dispatch: Dispatch, currentPath: s
} }
} }
async function fetchDashboard(args: InitDashboardArgs, dispatch: Dispatch, getState: () => StoreState): Promise<any> { async function fetchDashboard(
args: InitDashboardArgs,
dispatch: ThunkDispatch,
getState: () => StoreState
): Promise<DashboardDTO | null> {
try { try {
switch (args.routeInfo) { switch (args.routeInfo) {
case DashboardRouteInfo.Home: { case DashboardRouteInfo.Home: {
// load home dash // load home dash
const dashDTO = await getBackendSrv().get('/api/dashboards/home'); const dashDTO: DashboardDTO = await getBackendSrv().get('/api/dashboards/home');
// if user specified a custom home dashboard redirect to that // if user specified a custom home dashboard redirect to that
if (dashDTO.redirectUri) { if (dashDTO.redirectUri) {
const newUrl = locationUtil.stripBaseFromUrl(dashDTO.redirectUri); const newUrl = locationUtil.stripBaseFromUrl(dashDTO.redirectUri);
dispatch(updateLocation({ path: newUrl, replace: true })); dispatch(updateLocation({ path: newUrl, replace: true }));
return; return null;
} }
// disable some actions on the default home dashboard // disable some actions on the default home dashboard
...@@ -76,8 +83,8 @@ async function fetchDashboard(args: InitDashboardArgs, dispatch: Dispatch, getSt ...@@ -76,8 +83,8 @@ async function fetchDashboard(args: InitDashboardArgs, dispatch: Dispatch, getSt
return null; return null;
} }
const loaderSrv = args.$injector.get('dashboardLoaderSrv'); const loaderSrv: DashboardLoaderSrv = args.$injector.get('dashboardLoaderSrv');
const dashDTO = await loaderSrv.loadDashboard(args.urlType, args.urlSlug, args.urlUid); const dashDTO: DashboardDTO = await loaderSrv.loadDashboard(args.urlType, args.urlSlug, args.urlUid);
if (args.fixUrl && dashDTO.meta.url) { if (args.fixUrl && dashDTO.meta.url) {
// check if the current url is correct (might be old slug) // check if the current url is correct (might be old slug)
...@@ -95,6 +102,8 @@ async function fetchDashboard(args: InitDashboardArgs, dispatch: Dispatch, getSt ...@@ -95,6 +102,8 @@ async function fetchDashboard(args: InitDashboardArgs, dispatch: Dispatch, getSt
case DashboardRouteInfo.New: { case DashboardRouteInfo.New: {
return getNewDashboardModelData(args.urlFolderId); return getNewDashboardModelData(args.urlFolderId);
} }
default:
throw { message: 'Unknown route ' + args.routeInfo };
} }
} catch (err) { } catch (err) {
dispatch(setDashboardLoadingState(DashboardLoadingState.Error)); dispatch(setDashboardLoadingState(DashboardLoadingState.Error));
...@@ -149,7 +158,7 @@ export function initDashboard(args: InitDashboardArgs): ThunkResult<void> { ...@@ -149,7 +158,7 @@ export function initDashboard(args: InitDashboardArgs): ThunkResult<void> {
} }
// add missing orgId query param // add missing orgId query param
const storeState = getState() ; const storeState = getState();
if (!storeState.location.query.orgId) { if (!storeState.location.query.orgId) {
dispatch(updateLocation({ query: { orgId: storeState.user.orgId }, partial: true, replace: true })); dispatch(updateLocation({ query: { orgId: storeState.user.orgId }, partial: true, replace: true }));
} }
......
import config from 'app/core/config'; // Libraries
import _ from 'lodash'; import _ from 'lodash';
import $ from 'jquery'; import $ from 'jquery';
import Drop from 'tether-drop'; import Drop from 'tether-drop';
import { colors } from '@grafana/ui';
// Utils and servies
import { colors } from '@grafana/ui';
import config from 'app/core/config';
import coreModule from 'app/core/core_module'; import coreModule from 'app/core/core_module';
import { profiler } from 'app/core/profiler'; import { profiler } from 'app/core/profiler';
import appEvents from 'app/core/app_events'; import appEvents from 'app/core/app_events';
...@@ -13,6 +15,9 @@ import { DatasourceSrv, setDatasourceSrv } from 'app/features/plugins/datasource ...@@ -13,6 +15,9 @@ import { DatasourceSrv, setDatasourceSrv } from 'app/features/plugins/datasource
import { AngularLoader, setAngularLoader } from 'app/core/services/AngularLoader'; import { AngularLoader, setAngularLoader } from 'app/core/services/AngularLoader';
import { configureStore } from 'app/store/configureStore'; import { configureStore } from 'app/store/configureStore';
// Types
import { KioskUrlValue } from 'app/types';
export class GrafanaCtrl { export class GrafanaCtrl {
/** @ngInject */ /** @ngInject */
constructor( constructor(
...@@ -67,7 +72,7 @@ export class GrafanaCtrl { ...@@ -67,7 +72,7 @@ export class GrafanaCtrl {
} }
} }
function setViewModeBodyClass(body, mode, sidemenuOpen: boolean) { function setViewModeBodyClass(body, mode: KioskUrlValue, sidemenuOpen: boolean) {
body.removeClass('view-mode--tv'); body.removeClass('view-mode--tv');
body.removeClass('view-mode--kiosk'); body.removeClass('view-mode--kiosk');
body.removeClass('view-mode--inactive'); body.removeClass('view-mode--inactive');
......
import { DashboardAcl } from './acl'; import { DashboardAcl } from './acl';
export interface MutableDashboard { export interface MutableDashboard {
meta: { meta: DashboardMeta;
fullscreen: boolean; }
isEditing: boolean;
}; export interface DashboardDTO {
redirectUri?: string;
dashboard: DashboardDataDTO;
meta: DashboardMeta;
}
export interface DashboardMeta {
canSave?: boolean;
canEdit?: boolean;
canShare?: boolean;
canStar?: boolean;
canAdmin?: boolean;
url?: string;
folderId?: number;
fullscreen?: boolean;
isEditing?: boolean;
canMakeEditable?: boolean;
submenuEnabled?: boolean;
provisioned?: boolean;
focusPanelId?: boolean;
isStarred?: boolean;
showSettings?: boolean;
expires: string;
isSnapshot?: boolean;
folderTitle?: string;
folderUrl?: string;
created?: string;
}
export interface DashboardDataDTO {
title: string;
} }
export enum DashboardRouteInfo { export enum DashboardRouteInfo {
...@@ -22,6 +52,9 @@ export enum DashboardLoadingState { ...@@ -22,6 +52,9 @@ export enum DashboardLoadingState {
Done = 'Done', Done = 'Done',
} }
export const KIOSK_MODE_TV = 'tv';
export type KioskUrlValue = 'tv' | '1' | true;
export interface DashboardState { export interface DashboardState {
model: MutableDashboard | null; model: MutableDashboard | null;
loadingState: DashboardLoadingState; loadingState: DashboardLoadingState;
......
import { ThunkAction, ThunkDispatch as GenericThunkDispatch } from 'redux-thunk';
import { ActionOf } from 'app/core/redux';
import { NavIndex } from './navModel'; import { NavIndex } from './navModel';
import { LocationState } from './location'; import { LocationState } from './location';
import { AlertRulesState } from './alerting'; import { AlertRulesState } from './alerting';
...@@ -27,3 +30,10 @@ export interface StoreState { ...@@ -27,3 +30,10 @@ export interface StoreState {
user: UserState; user: UserState;
plugins: PluginsState; plugins: PluginsState;
} }
/*
* Utility type to get strongly types thunks
*/
export type ThunkResult<R> = ThunkAction<R, StoreState, undefined, ActionOf<any>>;
export type ThunkDispatch = GenericThunkDispatch<StoreState, undefined, any>;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment