diff --git a/i18n/messages-en.xtb b/i18n/messages-en.xtb
index 9f2d2a88266d..a0625a3657df 100644
--- a/i18n/messages-en.xtb
+++ b/i18n/messages-en.xtb
@@ -138,4 +138,6 @@
PodsAgeImages
+ namespace not selected
+ Selector for namespaces
\ No newline at end of file
diff --git a/i18n/messages-ja.xtb b/i18n/messages-ja.xtb
index ecb0cc339399..aec42fa6b1bf 100644
--- a/i18n/messages-ja.xtb
+++ b/i18n/messages-ja.xtb
@@ -138,4 +138,6 @@
PodsAgeImages
+ namespace not selected
+ Selector for namespaces
\ No newline at end of file
diff --git a/src/app/backend/resource/common/resourcechannels.go b/src/app/backend/resource/common/resourcechannels.go
index 90bf0f33d962..5063927c0762 100644
--- a/src/app/backend/resource/common/resourcechannels.go
+++ b/src/app/backend/resource/common/resourcechannels.go
@@ -333,7 +333,7 @@ func GetDaemonSetListChannel(client client.DaemonSetsNamespacer,
filteredItems = append(filteredItems, item)
}
}
- list.Items = filteredItems;
+ list.Items = filteredItems
for i := 0; i < numReads; i++ {
channel.List <- list
channel.Error <- err
@@ -366,8 +366,7 @@ func GetPetSetListChannel(client client.PetSetNamespacer,
filteredItems = append(filteredItems, item)
}
}
-
- petSets.Items = filteredItems;
+ petSets.Items = filteredItems
for i := 0; i < numReads; i++ {
channel.List <- petSets
channel.Error <- err
diff --git a/src/app/externs/uirouter.js b/src/app/externs/uirouter.js
new file mode 100644
index 000000000000..ced8252268db
--- /dev/null
+++ b/src/app/externs/uirouter.js
@@ -0,0 +1,32 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// 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.
+
+/**
+ * @fileoverview Externs for angular UI router that are missing from official ones.
+ *
+ * @externs
+ */
+
+const kdUiRouter = {};
+
+/**
+ * @constructor
+ */
+kdUiRouter.$stateProvider = function() {};
+
+/**
+ * @param {string} parent
+ * @param {Function} callback
+ */
+kdUiRouter.$stateProvider.prototype.decorator = function(parent, callback) {};
diff --git a/src/app/frontend/chrome/chrome.html b/src/app/frontend/chrome/chrome.html
index c3639b6e7b75..7e2c053672a1 100644
--- a/src/app/frontend/chrome/chrome.html
+++ b/src/app/frontend/chrome/chrome.html
@@ -16,13 +16,14 @@
diff --git a/src/app/frontend/chrome/chrome_controller.js b/src/app/frontend/chrome/chrome_controller.js
index 7edf0264aee4..8a875159d6d4 100644
--- a/src/app/frontend/chrome/chrome_controller.js
+++ b/src/app/frontend/chrome/chrome_controller.js
@@ -13,6 +13,7 @@
// limitations under the License.
import {actionbarViewName} from './chrome_state';
+import {stateName as workloadState} from 'workloads/workloads_state';
/**
* Controller for the chrome directive.
@@ -22,9 +23,10 @@ import {actionbarViewName} from './chrome_state';
export default class ChromeController {
/**
* @param {!ui.router.$state} $state
+ * @param {!angular.Scope} $scope
* @ngInject
*/
- constructor($state) {
+ constructor($state, $scope) {
/**
* By default this is true to show loading for the first page.
* @export {boolean}
@@ -33,8 +35,16 @@ export default class ChromeController {
/** @private {!ui.router.$state} */
this.state_ = $state;
+
+ this.registerStateChangeListeners($scope);
}
+ /**
+ * @return {string}
+ * @export
+ */
+ getLogoHref() { return this.state_.href(workloadState); }
+
/**
* @return {boolean}
* @export
diff --git a/src/app/frontend/chrome/chrome_directive.js b/src/app/frontend/chrome/chrome_directive.js
deleted file mode 100644
index ec372d6e462c..000000000000
--- a/src/app/frontend/chrome/chrome_directive.js
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// 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.
-
-import ChromeController from './chrome_controller';
-
-/**
- * Returns directive definition object for the chrome directive.
- *
- * @return {!angular.Directive}
- */
-export default function chromeDirective() {
- return {
- scope: {},
- bindToController: {},
- controller: ChromeController,
- controllerAs: 'ctrl',
- templateUrl: 'chrome/chrome.html',
- transclude: true,
- /**
- * @param {!angular.Scope} scope
- * @param {!angular.JQLite} elem
- * @param {!angular.Attributes} attrs
- * @param {!ChromeController} ctrl
- */
- link: function(scope, elem, attrs, ctrl) { ctrl.registerStateChangeListeners(scope); },
- };
-}
diff --git a/src/app/frontend/chrome/chrome_module.js b/src/app/frontend/chrome/chrome_module.js
index 8f832ae76333..c6f960adff3b 100644
--- a/src/app/frontend/chrome/chrome_module.js
+++ b/src/app/frontend/chrome/chrome_module.js
@@ -12,8 +12,9 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import chromeDirective from './chrome_directive';
+import stateConfig from './chrome_stateconfig';
import componentsModule from 'common/components/components_module';
+import namespaceModule from 'common/namespace/namespace_module';
/**
* Angular module containing navigation chrome for the application.
@@ -25,5 +26,6 @@ export default angular
'ngMaterial',
'ui.router',
componentsModule.name,
+ namespaceModule.name,
])
- .directive('chrome', chromeDirective);
+ .config(stateConfig);
diff --git a/src/app/frontend/chrome/chrome_state.js b/src/app/frontend/chrome/chrome_state.js
index 66fd3aaa9c55..886811bbb5a6 100644
--- a/src/app/frontend/chrome/chrome_state.js
+++ b/src/app/frontend/chrome/chrome_state.js
@@ -12,6 +12,12 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+/**
+* Name of the namespace state. This state should be used as a parent state for all root states.
+* It provides gobal namespace option for all URLs.
+*/
+export const stateName = 'chrome';
+
/** Name of the view. Can be used in state config to define toolbar view */
export const toolbarViewName = 'toolbar';
@@ -20,3 +26,22 @@ export const toolbarViewName = 'toolbar';
* be used for, e.g., breadcrumbs or view-specific action buttons.
*/
export const actionbarViewName = 'actionbar';
+
+/**
+ * Parameter name of the namespace selection param. Mostly for internal use.
+ */
+export const namespaceParam = 'namespace';
+
+/**
+ * All properties are @exported and in sync with URL param names.
+ * @final
+ */
+export class StateParams {
+ /**
+ * @param {string|undefined} namespace
+ */
+ constructor(namespace) {
+ /** @export {string|undefined} */
+ this.namespace = namespace;
+ }
+}
diff --git a/src/app/frontend/chrome/chrome_stateconfig.js b/src/app/frontend/chrome/chrome_stateconfig.js
new file mode 100644
index 000000000000..d1a4001a7b53
--- /dev/null
+++ b/src/app/frontend/chrome/chrome_stateconfig.js
@@ -0,0 +1,52 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// 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.
+
+import ChromeController from './chrome_controller';
+import {stateName, namespaceParam} from './chrome_state';
+
+/**
+ * Namespace is an abstract state with no path, but with one parameter ?namespace= that
+ * is always accepted (since namespace is above all).
+ *
+ * This state must always be the root in a state tree. This is enforced during app startup.
+ *
+ * @param {!ui.router.$stateProvider|kdUiRouter.$stateProvider} $stateProvider
+ * @ngInject
+ */
+export default function stateConfig($stateProvider) {
+ $stateProvider.state(stateName, {
+ url: `?${namespaceParam}`,
+ abstract: true,
+ templateUrl: 'chrome/chrome.html',
+ controller: ChromeController,
+ controllerAs: 'ctrl',
+ });
+ $stateProvider.decorator('parent', requireParentState);
+}
+
+/**
+ * @param {!Object} stateExtend
+ * @param {function(?):!ui.router.$state} parentFn
+ * @return {!ui.router.$state}
+ */
+function requireParentState(stateExtend, parentFn) {
+ /** @type {!ui.router.$state} */
+ let state = stateExtend['self'];
+ if (!state.parent && state.name !== stateName) {
+ throw new Error(
+ `State "${state.name}" requires parent state to be set to ` +
+ `${stateName}. This is likely a programming error.`);
+ }
+ return parentFn(stateExtend);
+}
diff --git a/src/app/frontend/common/components/breadcrumbs/breadcrumbs_service.js b/src/app/frontend/common/components/breadcrumbs/breadcrumbs_service.js
index 4a2be2f5abe5..fc09ae71d662 100644
--- a/src/app/frontend/common/components/breadcrumbs/breadcrumbs_service.js
+++ b/src/app/frontend/common/components/breadcrumbs/breadcrumbs_service.js
@@ -41,20 +41,22 @@ export class BreadcrumbsService {
}
/**
- * Returns parent state of the given state based on defined state parent name or if it is not
- * defined then based on direct parent state.
+ * Returns parent state of the given state based on defined breadcrumbs config state parent name.
*
* @param {!ui.router.$state} state
- * @return {!ui.router.$state}
+ * @return {ui.router.$state}
*/
getParentState(state) {
let conf = this.getBreadcrumbConfig(state);
- let result = state['parent'];
+ let result = null;
if (conf && conf.parent) {
- result = this.state_.get(conf.parent);
+ if (typeof conf.parent === 'string') {
+ result = this.state_.get(conf.parent);
+ } else {
+ result = conf.parent;
+ }
}
-
return result;
}
diff --git a/src/app/frontend/common/namespace/namespace_module.js b/src/app/frontend/common/namespace/namespace_module.js
new file mode 100644
index 000000000000..c32e15c84fed
--- /dev/null
+++ b/src/app/frontend/common/namespace/namespace_module.js
@@ -0,0 +1,28 @@
+
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// 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.
+
+import {namespaceSelectComponent} from './namespaceselect_component';
+
+/**
+ * Angular module global namespace selection components.
+ */
+export default angular
+ .module(
+ 'kubernetesDashboard.common.namespace',
+ [
+ 'ngMaterial',
+ 'ngResource',
+ ])
+ .component('kdNamespaceSelect', namespaceSelectComponent);
diff --git a/src/app/frontend/common/namespace/namespaceselect.html b/src/app/frontend/common/namespace/namespaceselect.html
new file mode 100644
index 000000000000..6600a3095fa0
--- /dev/null
+++ b/src/app/frontend/common/namespace/namespaceselect.html
@@ -0,0 +1,9 @@
+
+
+
+ {{$ctrl.formatNamespace(namespace)}}
+
+
+
diff --git a/src/app/frontend/common/namespace/namespaceselect_component.js b/src/app/frontend/common/namespace/namespaceselect_component.js
new file mode 100644
index 000000000000..aeb2ecfff0f2
--- /dev/null
+++ b/src/app/frontend/common/namespace/namespaceselect_component.js
@@ -0,0 +1,156 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// 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.
+
+import {namespaceParam} from 'chrome/chrome_state';
+
+/** Internal key for empty selection. To differentiate empty string from nulls. */
+const NAMESPACE_NOT_SELECTED = '__NAMESPACE_NOT_SELECTED__';
+
+/**
+ * @final
+ */
+export class NamespaceSelectController {
+ /**
+ * @param {!angular.$resource} $resource
+ * @param {!ui.router.$state} $state
+ * @param {!angular.Scope} $scope
+ * @ngInject
+ */
+ constructor($resource, $state, $scope) {
+ /**
+ * Initialized with all namespaces on first open.
+ * @export {!Array}
+ */
+ this.namespaces = [NAMESPACE_NOT_SELECTED];
+
+ /**
+ * Whether the list of namespaces has been initialized from the backend.
+ * @private {boolean}
+ */
+ this.namespacesInitialized_ = false;
+
+ /**
+ * Namespace that is selected in the select component.
+ * @export {string}
+ */
+ this.selectedNamespace;
+
+ /** @private {!angular.$resource} */
+ this.resource_ = $resource;
+
+ /** @private {!ui.router.$state} */
+ this.state_ = $state;
+
+ /** @private {!angular.Scope} */
+ this.scope_ = $scope;
+
+ /** @export */
+ this.i18n = i18n;
+ }
+
+ /**
+ * @export
+ */
+ $onInit() {
+ this.onNamespaceChanged_(this.state_.params);
+
+ this.scope_.$on('$stateChangeSuccess', (event, toState, /** Object */ toParams) => {
+ this.onNamespaceChanged_(toParams);
+ });
+ }
+
+ /**
+ * @param {Object} toParams
+ * @private
+ */
+ onNamespaceChanged_(toParams) {
+ if (toParams) {
+ /** @type {?string} */
+ let newNamespace = toParams[namespaceParam];
+ if (newNamespace) {
+ if (this.namespacesInitialized_) {
+ if (this.namespaces.indexOf(newNamespace) >= 0) {
+ this.selectedNamespace = newNamespace;
+ } else {
+ this.selectedNamespace = NAMESPACE_NOT_SELECTED;
+ }
+ this.changeNamespace();
+ } else {
+ this.namespaces = [newNamespace];
+ this.selectedNamespace = newNamespace;
+ }
+ } else {
+ this.selectedNamespace = NAMESPACE_NOT_SELECTED;
+ }
+ }
+ }
+
+ /**
+ * @return {string}
+ * @export
+ */
+ formatNamespace(namespace) {
+ if (namespace === NAMESPACE_NOT_SELECTED) {
+ return this.i18n.MSG_NAMESPACE_NOT_SELECTED;
+ } else {
+ return namespace;
+ }
+ }
+
+ /**
+ * @export
+ */
+ changeNamespace() {
+ let namespaceToGo = '';
+ if (this.selectedNamespace !== NAMESPACE_NOT_SELECTED) {
+ namespaceToGo = this.selectedNamespace;
+ }
+ this.state_.go('.', {[namespaceParam]: namespaceToGo});
+ }
+
+ /**
+ * @export
+ */
+ loadNamespacesIfNeeded() {
+ if (!this.namespacesInitialized_) {
+ /** @type {!angular.Resource} */
+ let resource = this.resource_('api/v1/namespace');
+
+ return resource.get().$promise.then((/** !backendApi.NamespaceList */ namespaceList) => {
+ this.namespaces = [NAMESPACE_NOT_SELECTED].concat(namespaceList.namespaces);
+ this.namespacesInitialized_ = true;
+ if (this.namespaces.indexOf(this.selectedNamespace) === -1) {
+ this.selectedNamespace = NAMESPACE_NOT_SELECTED;
+ this.changeNamespace();
+ }
+ });
+ }
+ }
+}
+
+/**
+ * @return {!angular.Directive}
+ */
+export const namespaceSelectComponent = {
+ controller: NamespaceSelectController,
+ templateUrl: 'common/namespace/namespaceselect.html',
+};
+
+const i18n = {
+ /** @export {string} @desc Text for dropdown item that indicates that no namespace was selected */
+ MSG_NAMESPACE_NOT_SELECTED: goog.getMsg('namespace not selected'),
+
+ /** @export {string} @desc Text describing what namespace selector is */
+ MSG_NAMESPACE_SELECT_ARIA_LABEL: goog.getMsg('Selector for namespaces'),
+};
diff --git a/src/app/frontend/common/resource/resourcedetail.js b/src/app/frontend/common/resource/resourcedetail.js
new file mode 100644
index 000000000000..4d34bcfd21ab
--- /dev/null
+++ b/src/app/frontend/common/resource/resourcedetail.js
@@ -0,0 +1,37 @@
+// Copyright 2015 Google Inc. All Rights Reserved.
+//
+// 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.
+
+/**
+ * Parameters for this state.
+ *
+ * All properties are @exported and in sync with URL param names.
+ * @final
+ */
+export class StateParams {
+ /**
+ * @param {string} objectNamespace
+ * @param {string} objectName
+ */
+ constructor(objectNamespace, objectName) {
+ /** @export {string} Namespace of this object. */
+ this.objectNamespace = objectNamespace;
+
+ /** @export {string} Name of this object. */
+ this.objectName = objectName;
+ }
+}
+
+export function appendDetailParamsToUrl(baseUrl) {
+ return `${baseUrl}/:objectNamespace/:objectName`;
+}
diff --git a/src/app/frontend/daemonsetdetail/daemonsetdetail_module.js b/src/app/frontend/daemonsetdetail/daemonsetdetail_module.js
index 7090c8b34619..1ffdc2813d96 100644
--- a/src/app/frontend/daemonsetdetail/daemonsetdetail_module.js
+++ b/src/app/frontend/daemonsetdetail/daemonsetdetail_module.js
@@ -13,6 +13,7 @@
// limitations under the License.
import componentsModule from 'common/components/components_module';
+import chromeModule from 'chrome/chrome_module';
import eventsModule from 'events/events_module';
import filtersModule from 'common/filters/filters_module';
import stateConfig from './daemonsetdetail_stateconfig';
@@ -31,6 +32,7 @@ export default angular
'ngResource',
'ui.router',
componentsModule.name,
+ chromeModule.name,
filtersModule.name,
eventsModule.name,
])
diff --git a/src/app/frontend/daemonsetdetail/daemonsetdetail_state.js b/src/app/frontend/daemonsetdetail/daemonsetdetail_state.js
index 677653723779..425fff24233f 100644
--- a/src/app/frontend/daemonsetdetail/daemonsetdetail_state.js
+++ b/src/app/frontend/daemonsetdetail/daemonsetdetail_state.js
@@ -14,23 +14,3 @@
/** Name of the state. Can be used in, e.g., $state.go method. */
export const stateName = 'daemonsetdetail';
-
-/**
- * Parameters for this state.
- *
- * All properties are @exported and in sync with URL param names.
- * @final
- */
-export class StateParams {
- /**
- * @param {string} namespace
- * @param {string} daemonSet
- */
- constructor(namespace, daemonSet) {
- /** @export {string} Namespace of this Daemon Set. */
- this.namespace = namespace;
-
- /** @export {string} Name of this Daemon Set. */
- this.daemonSet = daemonSet;
- }
-}
diff --git a/src/app/frontend/daemonsetdetail/daemonsetdetail_stateconfig.js b/src/app/frontend/daemonsetdetail/daemonsetdetail_stateconfig.js
index f234b6cfc9a8..3b45230a7e5b 100644
--- a/src/app/frontend/daemonsetdetail/daemonsetdetail_stateconfig.js
+++ b/src/app/frontend/daemonsetdetail/daemonsetdetail_stateconfig.js
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {actionbarViewName} from 'chrome/chrome_state';
+import {actionbarViewName, stateName as chromeStateName} from 'chrome/chrome_state';
import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_service';
import {stateName as daemonSetList, stateUrl} from 'daemonsetlist/daemonsetlist_state';
+import {appendDetailParamsToUrl} from 'common/resource/resourcedetail';
import {DaemonSetDetailController} from './daemonsetdetail_controller';
import {stateName} from './daemonsetdetail_state';
@@ -27,7 +28,8 @@ import {stateName} from './daemonsetdetail_state';
*/
export default function stateConfig($stateProvider) {
$stateProvider.state(stateName, {
- url: `${stateUrl}/:namespace/:daemonSet`,
+ url: appendDetailParamsToUrl(stateUrl),
+ parent: chromeStateName,
resolve: {
'daemonSetDetailResource': getDaemonSetDetailResource,
'daemonSetDetail': getDaemonSetDetail,
@@ -50,13 +52,13 @@ export default function stateConfig($stateProvider) {
}
/**
- * @param {!./daemonsetdetail_state.StateParams} $stateParams
+ * @param {!./../common/resource/resourcedetail.StateParams} $stateParams
* @param {!angular.$resource} $resource
* @return {!angular.Resource}
* @ngInject
*/
export function getDaemonSetDetailResource($resource, $stateParams) {
- return $resource(`api/v1/daemonset/${$stateParams.namespace}/${$stateParams.daemonSet}`);
+ return $resource(`api/v1/daemonset/${$stateParams.objectNamespace}/${$stateParams.objectName}`);
}
/**
diff --git a/src/app/frontend/daemonsetlist/daemonsetlist_component.js b/src/app/frontend/daemonsetlist/daemonsetlist_component.js
index e36ee1622a01..437ba9f22c7e 100644
--- a/src/app/frontend/daemonsetlist/daemonsetlist_component.js
+++ b/src/app/frontend/daemonsetlist/daemonsetlist_component.js
@@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {StateParams, stateName} from 'daemonsetdetail/daemonsetdetail_state';
+import {StateParams} from 'common/resource/resourcedetail';
+import {stateName} from 'daemonsetdetail/daemonsetdetail_state';
/**
* @final
diff --git a/src/app/frontend/daemonsetlist/daemonsetlist_module.js b/src/app/frontend/daemonsetlist/daemonsetlist_module.js
index 41d9bdf5b53d..a1c022bad74f 100644
--- a/src/app/frontend/daemonsetlist/daemonsetlist_module.js
+++ b/src/app/frontend/daemonsetlist/daemonsetlist_module.js
@@ -12,7 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import componentsModule from './../common/components/components_module';
+import componentsModule from 'common/components/components_module';
+import chromeModule from 'chrome/chrome_module';
import filtersModule from 'common/filters/filters_module';
import stateConfig from './daemonsetlist_stateconfig';
import {daemonSetCardListComponent} from './daemonsetlist_component';
@@ -32,8 +33,8 @@ export default angular
'ui.router',
filtersModule.name,
componentsModule.name,
+ chromeModule.name,
daemonSetDetailModule.name,
-
])
.config(stateConfig)
.component('kdDaemonSetCardList', daemonSetCardListComponent);
diff --git a/src/app/frontend/daemonsetlist/daemonsetlist_stateconfig.js b/src/app/frontend/daemonsetlist/daemonsetlist_stateconfig.js
index 740c356df40e..55257fc2c933 100644
--- a/src/app/frontend/daemonsetlist/daemonsetlist_stateconfig.js
+++ b/src/app/frontend/daemonsetlist/daemonsetlist_stateconfig.js
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {actionbarViewName} from 'chrome/chrome_state';
+import {actionbarViewName, stateName as chromeStateName} from 'chrome/chrome_state';
import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_service';
import {stateName as workloadsState} from 'workloads/workloads_state';
@@ -28,6 +28,7 @@ import {stateName, stateUrl} from './daemonsetlist_state';
export default function stateConfig($stateProvider) {
$stateProvider.state(stateName, {
url: stateUrl,
+ parent: chromeStateName,
resolve: {
'daemonSetList': resolveDaemonSetList,
},
diff --git a/src/app/frontend/deploy/deploy_stateconfig.js b/src/app/frontend/deploy/deploy_stateconfig.js
index abe9b54835d3..485baa0dd0e3 100644
--- a/src/app/frontend/deploy/deploy_stateconfig.js
+++ b/src/app/frontend/deploy/deploy_stateconfig.js
@@ -14,6 +14,7 @@
import DeployController from './deploy_controller';
import {stateName} from './deploy_state';
+import {stateName as chromeStateName} from 'chrome/chrome_state';
/**
* Configures states for the deploy view.
@@ -26,6 +27,7 @@ export default function stateConfig($stateProvider) {
controller: DeployController,
controllerAs: 'ctrl',
url: '/deploy',
+ parent: chromeStateName,
resolve: {
'namespaces': resolveNamespaces,
'protocolsResource': getProtocolsResource,
diff --git a/src/app/frontend/deploy/upload.html b/src/app/frontend/deploy/upload.html
index 8bc9acb3684d..e6de71317afe 100644
--- a/src/app/frontend/deploy/upload.html
+++ b/src/app/frontend/deploy/upload.html
@@ -17,7 +17,7 @@
-
+
diff --git a/src/app/frontend/deploymentdetail/deploymentdetail_state.js b/src/app/frontend/deploymentdetail/deploymentdetail_state.js
index c6a3585001ad..2c729ae4fc63 100644
--- a/src/app/frontend/deploymentdetail/deploymentdetail_state.js
+++ b/src/app/frontend/deploymentdetail/deploymentdetail_state.js
@@ -16,24 +16,4 @@
export const stateName = 'deploymentdetail';
/** Absolute URL of the state. */
-export const stateUrl = '/deployment/:namespace/:deployment';
-
-/**
- * Parameters for this state.
- *
- * All properties are @exported and in sync with URL param names.
- * @final
- */
-export class StateParams {
- /**
- * @param {string} namespace
- * @param {string} deployment
- */
- constructor(namespace, deployment) {
- /** @export {string} Namespace of this Deployment. */
- this.namespace = namespace;
-
- /** @export {string} Name of this Deployment. */
- this.deployment = deployment;
- }
-}
+export const stateUrl = '/deployment';
diff --git a/src/app/frontend/deploymentdetail/deploymentdetail_stateconfig.js b/src/app/frontend/deploymentdetail/deploymentdetail_stateconfig.js
index 00ade45ad45c..62a3928bd277 100644
--- a/src/app/frontend/deploymentdetail/deploymentdetail_stateconfig.js
+++ b/src/app/frontend/deploymentdetail/deploymentdetail_stateconfig.js
@@ -12,9 +12,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {actionbarViewName} from 'chrome/chrome_state';
+import {actionbarViewName, stateName as chromeStateName} from 'chrome/chrome_state';
import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_service';
import {stateName as deploymentList} from 'deploymentlist/deploymentlist_state';
+import {appendDetailParamsToUrl} from 'common/resource/resourcedetail';
import {DeploymentDetailController} from './deploymentdetail_controller';
import {stateName, stateUrl} from './deploymentdetail_state';
@@ -27,7 +28,8 @@ import {stateName, stateUrl} from './deploymentdetail_state';
*/
export default function stateConfig($stateProvider) {
$stateProvider.state(stateName, {
- url: stateUrl,
+ url: appendDetailParamsToUrl(stateUrl),
+ parent: chromeStateName,
resolve: {
'deploymentDetailResource': getDeploymentDetailResource,
'deploymentDetail': getDeploymentDetail,
@@ -50,13 +52,13 @@ export default function stateConfig($stateProvider) {
}
/**
- * @param {!./deploymentdetail_state.StateParams} $stateParams
+ * @param {!./../common/resource/resourcedetail.StateParams} $stateParams
* @param {!angular.$resource} $resource
* @return {!angular.Resource}
* @ngInject
*/
export function getDeploymentDetailResource($resource, $stateParams) {
- return $resource(`api/v1/deployment/${$stateParams.namespace}/${$stateParams.deployment}`);
+ return $resource(`api/v1/deployment/${$stateParams.objectNamespace}/${$stateParams.objectName}`);
}
/**
diff --git a/src/app/frontend/deploymentlist/deploymentcard_component.js b/src/app/frontend/deploymentlist/deploymentcard_component.js
index e61d5f187947..46baa542abac 100644
--- a/src/app/frontend/deploymentlist/deploymentcard_component.js
+++ b/src/app/frontend/deploymentlist/deploymentcard_component.js
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {StateParams} from 'deploymentdetail/deploymentdetail_state';
+import {StateParams} from 'common/resource/resourcedetail';
import {stateName} from 'deploymentdetail/deploymentdetail_state';
/**
diff --git a/src/app/frontend/deploymentlist/deploymentlist_module.js b/src/app/frontend/deploymentlist/deploymentlist_module.js
index 23fcc5f32915..6ece07bf225a 100644
--- a/src/app/frontend/deploymentlist/deploymentlist_module.js
+++ b/src/app/frontend/deploymentlist/deploymentlist_module.js
@@ -15,6 +15,7 @@
import stateConfig from './deploymentlist_stateconfig';
import filtersModule from 'common/filters/filters_module';
import componentsModule from 'common/components/components_module';
+import chromeModule from 'chrome/chrome_module';
import {deploymentCardComponent} from './deploymentcard_component';
import {deploymentCardListComponent} from './deploymentcardlist_component';
import deploymentDetailModule from 'deploymentdetail/deploymentdetail_module';
@@ -33,6 +34,7 @@ export default angular
'ui.router',
filtersModule.name,
componentsModule.name,
+ chromeModule.name,
deploymentDetailModule.name,
])
.config(stateConfig)
diff --git a/src/app/frontend/deploymentlist/deploymentlist_stateconfig.js b/src/app/frontend/deploymentlist/deploymentlist_stateconfig.js
index 65cd4f746baa..a8a0d176d96d 100644
--- a/src/app/frontend/deploymentlist/deploymentlist_stateconfig.js
+++ b/src/app/frontend/deploymentlist/deploymentlist_stateconfig.js
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import {actionbarViewName} from 'chrome/chrome_state';
+import {actionbarViewName, stateName as chromeStateName} from 'chrome/chrome_state';
import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_service';
import {stateName as workloadsState} from 'workloads/workloads_state';
@@ -29,6 +29,7 @@ import {DeploymentListActionBarController} from './deploymentlistactionbar_contr
export default function stateConfig($stateProvider) {
$stateProvider.state(stateName, {
url: stateUrl,
+ parent: chromeStateName,
resolve: {
'deployments': resolveDeployments,
},
@@ -55,11 +56,12 @@ export default function stateConfig($stateProvider) {
/**
* @param {!angular.$resource} $resource
+ * @param {!./../chrome/chrome_state.StateParams} $stateParams
* @return {!angular.$q.Promise}
* @ngInject
*/
-export function resolveDeployments($resource) {
+export function resolveDeployments($resource, $stateParams) {
/** @type {!angular.Resource} */
- let resource = $resource('api/v1/deployment');
+ let resource = $resource(`api/v1/deployment/${$stateParams.namespace || ''}`);
return resource.get().$promise;
}
diff --git a/src/app/frontend/error/error_module.js b/src/app/frontend/error/error_module.js
index 2d31c8aef948..812591d136a5 100644
--- a/src/app/frontend/error/error_module.js
+++ b/src/app/frontend/error/error_module.js
@@ -14,6 +14,7 @@
import {stateName, StateParams} from './internalerror_state';
import stateConfig from './internalerror_stateconfig';
+import chromeModule from 'chrome/chrome_module';
/**
* Angular module for error views.
@@ -23,6 +24,7 @@ export default angular
'kubernetesDashboard.error',
[
'ui.router',
+ chromeModule.name,
])
.config(stateConfig)
.run(errorConfig);
diff --git a/src/app/frontend/error/internalerror_stateconfig.js b/src/app/frontend/error/internalerror_stateconfig.js
index 19999b485d72..aa375d6c0bff 100644
--- a/src/app/frontend/error/internalerror_stateconfig.js
+++ b/src/app/frontend/error/internalerror_stateconfig.js
@@ -15,6 +15,8 @@
import {InternalErrorController} from './internalerror_controller';
import {stateName, StateParams} from './internalerror_state';
+import {stateName as chromeStateName} from 'chrome/chrome_state';
+
/**
* Configures states for the internal error view.
*
@@ -24,6 +26,7 @@ import {stateName, StateParams} from './internalerror_state';
export default function stateConfig($stateProvider) {
$stateProvider.state(stateName, {
controller: InternalErrorController,
+ parent: chromeStateName,
controllerAs: 'ctrl',
params: new StateParams(/** @type {!angular.$http.Response} */ ({})),
templateUrl: 'error/internalerror.html',
diff --git a/src/app/frontend/index.html b/src/app/frontend/index.html
index 131bad056178..e49743a26ee2 100644
--- a/src/app/frontend/index.html
+++ b/src/app/frontend/index.html
@@ -44,9 +44,7 @@
experience.
-
-