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 @@ Pods Age Images + 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 @@ Pods Age Images + 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 @@
- +

kubernetes

+
@@ -34,6 +35,8 @@

-
+
+
+
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.

- -
-
+