component.ts 5.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

15
import {Component, OnInit} from '@angular/core';
S
Shu Muto 已提交
16
import {ActivatedRoute, NavigationEnd, Params, Route, Router} from '@angular/router';
17
import {Breadcrumb} from '@api/frontendapi';
18
import {distinctUntilChanged, filter} from 'rxjs/operators';
19
import {POD_DETAIL_ROUTE} from '../../../resource/workloads/pod/routing';
20
import {REPLICASET_DETAIL_ROUTE} from '../../../resource/workloads/replicaset/routing';
21 22
import {REPLICATIONCONTROLLER_DETAIL_ROUTE} from '../../../resource/workloads/replicationcontroller/routing';
import {SEARCH_QUERY_STATE_PARAM} from '../../params/params';
23 24 25

export const LOGS_PARENT_PLACEHOLDER = '___LOGS_PARENT_PLACEHOLDER___';
export const EXEC_PARENT_PLACEHOLDER = '___EXEC_PARENT_PLACEHOLDER___';
26
export const SEARCH_BREADCRUMB_PLACEHOLDER = '___SEARCH_BREADCRUMB_PLACEHOLDER___';
27

28 29 30 31 32 33 34
@Component({
  selector: 'kd-breadcrumbs',
  templateUrl: './template.html',
  styleUrls: ['./style.scss'],
})
export class BreadcrumbsComponent implements OnInit {
  breadcrumbs: Breadcrumb[];
35

36
  constructor(private readonly _router: Router, private readonly _activatedRoute: ActivatedRoute) {}
37 38

  ngOnInit(): void {
39
    this._initBreadcrumbs();
40 41 42 43
    this._registerNavigationHook();
  }

  private _registerNavigationHook(): void {
S
Shu Muto 已提交
44
    this._router.events
45 46
      .pipe(
        filter(event => event instanceof NavigationEnd),
47
        distinctUntilChanged()
48
      )
S
Shu Muto 已提交
49 50 51
      .subscribe(() => {
        this._initBreadcrumbs();
      });
52 53
  }

54 55
  private _initBreadcrumbs(): void {
    const currentRoute = this._getCurrentRoute();
56
    const url = this._router.url.includes('?') ? this._router.url.split('?')[0] : '';
57
    let urlArray = url.split('/');
58 59 60 61
    let routeParamsCount =
      currentRoute.routeConfig.data && currentRoute.routeConfig.data.routeParamsCount
        ? +currentRoute.routeConfig.data.routeParamsCount
        : currentRoute.routeConfig.path.split('/').length;
62

63 64
    this.breadcrumbs = [
      {
65
        label: this._getBreadcrumbLabel(currentRoute.routeConfig, currentRoute.snapshot.params),
S
Shu Muto 已提交
66 67 68 69
        stateLink:
          currentRoute.routeConfig.data && currentRoute.routeConfig.data.link
            ? currentRoute.routeConfig.data.link
            : urlArray,
70 71
      },
    ];
72

73
    let route: Route;
S
Shu Muto 已提交
74 75 76 77 78 79
    if (
      currentRoute &&
      currentRoute.routeConfig &&
      currentRoute.routeConfig.data &&
      currentRoute.routeConfig.data.parent
    ) {
80 81
      if (currentRoute.routeConfig.data.parent === LOGS_PARENT_PLACEHOLDER) {
        route = this._getLogsParent(currentRoute.snapshot.params);
M
Marcin Maciaszczyk 已提交
82
        urlArray = ['', urlArray[urlArray.length - 1], urlArray[urlArray.length - 3], urlArray[urlArray.length - 2]];
83
        routeParamsCount = 0;
84
      } else if (currentRoute.routeConfig.data.parent === EXEC_PARENT_PLACEHOLDER) {
85
        route = POD_DETAIL_ROUTE;
86
        urlArray = ['', 'pod', urlArray[urlArray.length - 3], urlArray[urlArray.length - 2]];
87 88 89
        routeParamsCount = 0;
      } else {
        route = currentRoute.routeConfig.data.parent;
90 91
      }

92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
      while (route) {
        // Trim URL by number of path parameters defined on previous route.
        urlArray = urlArray.slice(0, urlArray.length - routeParamsCount);
        routeParamsCount = route.path.split('/').length;

        this.breadcrumbs.push({
          label: this._getBreadcrumbLabel(route, currentRoute.snapshot.params),
          stateLink: route.data.link ? route.data.link : urlArray,
        });

        // Explore the route tree to the root route (parent references have to be defined by us on
        // each route).
        if (route && route.data && route.data.parent) {
          route = route.data.parent;
        } else {
          break;
        }
      }
110 111
    }

112
    this.breadcrumbs.reverse();
113 114
  }

S
Shu Muto 已提交
115
  private _getLogsParent(params: Params): Route | undefined {
116 117 118
    const resourceType = params['resourceType'];
    if (resourceType === 'pod') {
      return POD_DETAIL_ROUTE;
119 120 121 122
    } else if (resourceType === 'replicationcontroller') {
      return REPLICATIONCONTROLLER_DETAIL_ROUTE;
    } else if (resourceType === 'replicaset') {
      return REPLICASET_DETAIL_ROUTE;
123
    }
M
Marcin Maciaszczyk 已提交
124
    return undefined;
125 126
  }

127 128 129 130 131 132 133
  private _getCurrentRoute(): ActivatedRoute {
    let route = this._activatedRoute.root;
    while (route && route.firstChild) {
      route = route.firstChild;
    }
    return route;
  }
134

135 136 137 138 139 140
  private _getBreadcrumbLabel(route: Route, params: Params) {
    if (route && route.data && route.data.breadcrumb) {
      let breadcrumb = route.data.breadcrumb as string;
      if (breadcrumb.startsWith('{{') && breadcrumb.endsWith('}}')) {
        breadcrumb = breadcrumb.slice(2, breadcrumb.length - 2).trim();
        breadcrumb = params[breadcrumb];
141 142
      } else if (breadcrumb === SEARCH_BREADCRUMB_PLACEHOLDER) {
        return `Search for ${this._activatedRoute.snapshot.queryParams[SEARCH_QUERY_STATE_PARAM]}`;
143 144 145 146 147
      }
      return breadcrumb;
    } else if (route && route.component) {
      return route.component.name;
    }
M
Marcin Maciaszczyk 已提交
148
    return 'Unknown';
149 150
  }
}