diff --git a/public/app/core/selectors/navModel.ts b/public/app/core/selectors/navModel.ts index 8b3a3edd84e..aa508616962 100644 --- a/public/app/core/selectors/navModel.ts +++ b/public/app/core/selectors/navModel.ts @@ -15,7 +15,7 @@ function getNotFoundModel(): NavModel { }; } -export function getNavModel(navIndex: NavIndex, id: string): NavModel { +export function getNavModel(navIndex: NavIndex, id: string, fallback?: NavModel): NavModel { if (navIndex[id]) { const node = navIndex[id]; const main = { @@ -33,7 +33,11 @@ export function getNavModel(navIndex: NavIndex, id: string): NavModel { node: node, main: main, }; - } else { - return getNotFoundModel(); } + + if (fallback) { + return fallback; + } + + return getNotFoundModel(); } diff --git a/public/app/features/folders/FolderPermissions.tsx b/public/app/features/folders/FolderPermissions.tsx index 1dc34aaba1e..512927c24e6 100644 --- a/public/app/features/folders/FolderPermissions.tsx +++ b/public/app/features/folders/FolderPermissions.tsx @@ -12,6 +12,7 @@ import { getNavModel } from 'app/core/selectors/navModel'; import { NavModel, StoreState, FolderState } from 'app/types'; import { getFolderByUid } from './state/actions'; import { PermissionsStore } from 'app/stores/PermissionsStore/PermissionsStore'; +import { getLoadingNav } from './state/navModel'; export interface Props { navModel: NavModel; @@ -48,7 +49,7 @@ export class FolderPermissions extends Component { const { navModel, permissions, backendSrv, folder } = this.props; if (folder.id === 0) { - return

Loading

; + return ; } const dashboardId = folder.id; @@ -84,7 +85,7 @@ export class FolderPermissions extends Component { const mapStateToProps = (state: StoreState) => { const uid = state.location.routeParams.uid; return { - navModel: getNavModel(state.navIndex, `folder-permissions-${uid}`), + navModel: getNavModel(state.navIndex, `folder-permissions-${uid}`, getLoadingNav(1)), folderUid: uid, folder: state.folder, }; diff --git a/public/app/features/folders/FolderSettingsPage.tsx b/public/app/features/folders/FolderSettingsPage.tsx index 2aff0e3e1c4..1eb7ccafc65 100644 --- a/public/app/features/folders/FolderSettingsPage.tsx +++ b/public/app/features/folders/FolderSettingsPage.tsx @@ -6,6 +6,7 @@ import appEvents from 'app/core/app_events'; import { getNavModel } from 'app/core/selectors/navModel'; import { NavModel, StoreState, FolderState } from 'app/types'; import { getFolderByUid, setFolderTitle, saveFolder, deleteFolder } from './state/actions'; +import { getLoadingNav } from './state/navModel'; export interface Props { navModel: NavModel; @@ -86,8 +87,9 @@ export class FolderSettingsPage extends PureComponent { const mapStateToProps = (state: StoreState) => { const uid = state.location.routeParams.uid; + return { - navModel: getNavModel(state.navIndex, `folder-settings-${uid}`), + navModel: getNavModel(state.navIndex, `folder-settings-${uid}`, getLoadingNav(2)), folderUid: uid, folder: state.folder, }; diff --git a/public/app/features/folders/state/navModel.ts b/public/app/features/folders/state/navModel.ts index 614bb30f2d8..e6ef763d019 100644 --- a/public/app/features/folders/state/navModel.ts +++ b/public/app/features/folders/state/navModel.ts @@ -1,4 +1,4 @@ -import { FolderDTO, NavModelItem } from 'app/types'; +import { FolderDTO, NavModelItem, NavModel } from 'app/types'; export function buildNavModel(folder: FolderDTO): NavModelItem { return { @@ -33,3 +33,21 @@ export function buildNavModel(folder: FolderDTO): NavModelItem { ], }; } + +export function getLoadingNav(tabIndex: number): NavModel { + const main = buildNavModel({ + id: 1, + uid: 'loading', + title: 'Loading', + url: 'url', + canSave: false, + version: 0, + }); + + main.children[tabIndex].active = true; + + return { + main: main, + node: main.children[tabIndex], + }; +} diff --git a/public/app/features/teams/TeamPages.tsx b/public/app/features/teams/TeamPages.tsx index f28bde518d2..bbc8b7013ca 100644 --- a/public/app/features/teams/TeamPages.tsx +++ b/public/app/features/teams/TeamPages.tsx @@ -7,10 +7,11 @@ import PageHeader from 'app/core/components/PageHeader/PageHeader'; import TeamMembers from './TeamMembers'; import TeamSettings from './TeamSettings'; import TeamGroupSync from './TeamGroupSync'; -import { NavModel, Team } from '../../types'; +import { NavModel, Team } from 'app/types'; import { loadTeam } from './state/actions'; import { getTeam } from './state/selectors'; -import { getNavModel } from '../../core/selectors/navModel'; +import { getTeamLoadingNav } from './state/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; import { getRouteParamsId, getRouteParamsPage } from '../../core/selectors/location'; export interface Props { @@ -89,9 +90,10 @@ export class TeamPages extends PureComponent { function mapStateToProps(state) { const teamId = getRouteParamsId(state.location); const pageName = getRouteParamsPage(state.location) || 'members'; + const teamLoadingNav = getTeamLoadingNav(pageName); return { - navModel: getNavModel(state.navIndex, `team-${pageName}-${teamId}`), + navModel: getNavModel(state.navIndex, `team-${pageName}-${teamId}`, teamLoadingNav), teamId: teamId, pageName: pageName, team: getTeam(state.team, teamId), diff --git a/public/app/features/teams/state/actions.ts b/public/app/features/teams/state/actions.ts index 63bea743607..d948dc1c5a3 100644 --- a/public/app/features/teams/state/actions.ts +++ b/public/app/features/teams/state/actions.ts @@ -1,8 +1,8 @@ import { ThunkAction } from 'redux-thunk'; import { getBackendSrv } from 'app/core/services/backend_srv'; -import { NavModelItem, StoreState, Team, TeamGroup, TeamMember } from 'app/types'; +import { StoreState, Team, TeamGroup, TeamMember } from 'app/types'; import { updateNavIndex, UpdateNavIndexAction } from 'app/core/actions'; -import config from 'app/core/config'; +import { buildNavModel } from './navModel'; export enum ActionTypes { LoadTeams = 'LOAD_TEAMS', @@ -90,45 +90,6 @@ export function loadTeams(): ThunkResult { }; } -function buildNavModel(team: Team): NavModelItem { - const navModel = { - img: team.avatarUrl, - id: 'team-' + team.id, - subTitle: 'Manage members & settings', - url: '', - text: team.name, - breadcrumbs: [{ title: 'Teams', url: 'org/teams' }], - children: [ - { - active: false, - icon: 'gicon gicon-team', - id: `team-members-${team.id}`, - text: 'Members', - url: `org/teams/edit/${team.id}/members`, - }, - { - active: false, - icon: 'fa fa-fw fa-sliders', - id: `team-settings-${team.id}`, - text: 'Settings', - url: `org/teams/edit/${team.id}/settings`, - }, - ], - }; - - if (config.buildInfo.isEnterprise) { - navModel.children.push({ - active: false, - icon: 'fa fa-fw fa-refresh', - id: `team-groupsync-${team.id}`, - text: 'External group sync', - url: `org/teams/edit/${team.id}/groupsync`, - }); - } - - return navModel; -} - export function loadTeam(id: number): ThunkResult { return async dispatch => { const response = await getBackendSrv().get(`/api/teams/${id}`); diff --git a/public/app/features/teams/state/navModel.ts b/public/app/features/teams/state/navModel.ts new file mode 100644 index 00000000000..2fd5a68e680 --- /dev/null +++ b/public/app/features/teams/state/navModel.ts @@ -0,0 +1,67 @@ +import { Team, NavModelItem, NavModel } from 'app/types'; +import config from 'app/core/config'; + +export function buildNavModel(team: Team): NavModelItem { + const navModel = { + img: team.avatarUrl, + id: 'team-' + team.id, + subTitle: 'Manage members & settings', + url: '', + text: team.name, + breadcrumbs: [{ title: 'Teams', url: 'org/teams' }], + children: [ + { + active: false, + icon: 'gicon gicon-team', + id: `team-members-${team.id}`, + text: 'Members', + url: `org/teams/edit/${team.id}/members`, + }, + { + active: false, + icon: 'fa fa-fw fa-sliders', + id: `team-settings-${team.id}`, + text: 'Settings', + url: `org/teams/edit/${team.id}/settings`, + }, + ], + }; + + if (config.buildInfo.isEnterprise) { + navModel.children.push({ + active: false, + icon: 'fa fa-fw fa-refresh', + id: `team-groupsync-${team.id}`, + text: 'External group sync', + url: `org/teams/edit/${team.id}/groupsync`, + }); + } + + return navModel; +} + +export function getTeamLoadingNav(pageName: string): NavModel { + const main = buildNavModel({ + avatarUrl: 'public/img/user_profile.png', + id: 1, + name: 'Loading', + email: 'loading', + memberCount: 0, + }); + + let node: NavModelItem; + + // find active page + for (const child of main.children) { + if (child.id.indexOf(pageName) > 0) { + child.active = true; + node = child; + break; + } + } + + return { + main: main, + node: node, + }; +}