From f878ab331bfd8150ebb3d4a361d76dfbe5dac79e Mon Sep 17 00:00:00 2001 From: Piotr Bryk Date: Thu, 14 Jul 2016 15:19:39 +0200 Subject: [PATCH] Config map details and list frontend (#1019) --- i18n/messages-en.xtb | 12 +++ i18n/messages-ja.xtb | 12 +++ src/app/externs/backendapi.js | 25 ++++++ .../frontend/configmapdetail/actionbar.html | 21 +++++ .../configmapdetail/actionbar_controller.js | 36 ++++++++ .../configmapdetail/configmapdetail.html | 27 ++++++ .../configmapdetail_controller.js | 35 ++++++++ .../configmapdetail/configmapdetail_module.js | 40 +++++++++ .../configmapdetail/configmapdetail_state.js | 16 ++++ .../configmapdetail_stateconfig.js | 76 ++++++++++++++++ .../configmapdetail/configmapinfo.html | 31 +++++++ .../configmapinfo_component.js | 57 ++++++++++++ src/app/frontend/configmaplist/actionbar.html | 17 ++++ .../frontend/configmaplist/configmapcard.html | 47 ++++++++++ .../configmaplist/configmapcard_component.js | 86 +++++++++++++++++++ .../configmaplist/configmapcardlist.html | 38 ++++++++ .../configmapcardlist_component.js | 49 +++++++++++ .../frontend/configmaplist/configmaplist.html | 23 +++++ .../configmaplist/configmaplist_controller.js | 35 ++++++++ .../configmaplist/configmaplist_module.js | 40 +++++++++ .../configmaplist/configmaplist_state.js | 19 ++++ .../configmaplist_stateconfig.js | 69 +++++++++++++++ src/app/frontend/index_module.js | 4 + .../actionbar_controller_test.js | 31 +++++++ .../configmapdetail_controller_test.js | 29 +++++++ .../configmapinfo_component_test.js | 34 ++++++++ .../configmapcard_component_test.js | 41 +++++++++ .../configmapcardlist_component_test.js | 29 +++++++ .../configmaplist_controller_test.js | 47 ++++++++++ .../configmaplist_stateconfig_test.js | 44 ++++++++++ 30 files changed, 1070 insertions(+) create mode 100644 src/app/frontend/configmapdetail/actionbar.html create mode 100644 src/app/frontend/configmapdetail/actionbar_controller.js create mode 100644 src/app/frontend/configmapdetail/configmapdetail.html create mode 100644 src/app/frontend/configmapdetail/configmapdetail_controller.js create mode 100644 src/app/frontend/configmapdetail/configmapdetail_module.js create mode 100644 src/app/frontend/configmapdetail/configmapdetail_state.js create mode 100644 src/app/frontend/configmapdetail/configmapdetail_stateconfig.js create mode 100644 src/app/frontend/configmapdetail/configmapinfo.html create mode 100644 src/app/frontend/configmapdetail/configmapinfo_component.js create mode 100644 src/app/frontend/configmaplist/actionbar.html create mode 100644 src/app/frontend/configmaplist/configmapcard.html create mode 100644 src/app/frontend/configmaplist/configmapcard_component.js create mode 100644 src/app/frontend/configmaplist/configmapcardlist.html create mode 100644 src/app/frontend/configmaplist/configmapcardlist_component.js create mode 100644 src/app/frontend/configmaplist/configmaplist.html create mode 100644 src/app/frontend/configmaplist/configmaplist_controller.js create mode 100644 src/app/frontend/configmaplist/configmaplist_module.js create mode 100644 src/app/frontend/configmaplist/configmaplist_state.js create mode 100644 src/app/frontend/configmaplist/configmaplist_stateconfig.js create mode 100644 src/test/frontend/configmapdetail/actionbar_controller_test.js create mode 100644 src/test/frontend/configmapdetail/configmapdetail_controller_test.js create mode 100644 src/test/frontend/configmapdetail/configmapinfo_component_test.js create mode 100644 src/test/frontend/configmaplist/configmapcard_component_test.js create mode 100644 src/test/frontend/configmaplist/configmapcardlist_component_test.js create mode 100644 src/test/frontend/configmaplist/configmaplist_controller_test.js create mode 100644 src/test/frontend/configmaplist/configmaplist_stateconfig_test.js diff --git a/i18n/messages-en.xtb b/i18n/messages-en.xtb index 9fc5114f1..472303154 100644 --- a/i18n/messages-en.xtb +++ b/i18n/messages-en.xtb @@ -481,4 +481,16 @@ Port cannot be empty Target port cannot be empty Font size: + Config Maps + Config Map + Data + Details + Name + Namespace + Labels + Created at + Config Map + Name + Labels + Age \ No newline at end of file diff --git a/i18n/messages-ja.xtb b/i18n/messages-ja.xtb index 452e8cc90..03322ccb4 100644 --- a/i18n/messages-ja.xtb +++ b/i18n/messages-ja.xtb @@ -670,4 +670,16 @@ Port cannot be empty Target port cannot be empty Font size: + Config Maps + Config Map + Data + Details + Name + Namespace + Labels + Created at + Config Map + Name + Labels + Age \ No newline at end of file diff --git a/src/app/externs/backendapi.js b/src/app/externs/backendapi.js index 657c8f9bb..f1c2fd087 100644 --- a/src/app/externs/backendapi.js +++ b/src/app/externs/backendapi.js @@ -281,6 +281,31 @@ backendApi.PetSetDetail; */ backendApi.PetSetList; +/** + * @typedef {{ + * objectMeta: !backendApi.ObjectMeta, + * typeMeta: !backendApi.TypeMeta, + * }} + */ +backendApi.ConfigMap; + +/** + * @typedef {{ + * objectMeta: !backendApi.ObjectMeta, + * typeMeta: !backendApi.TypeMeta, + * data: !Object, + * }} + */ +backendApi.ConfigMapDetail; + +/** + * @typedef {{ + * items: !Array, + * listMeta: !backendApi.ListMeta + * }} + */ +backendApi.ConfigMapList; + /** * @typedef {{ * objectMeta: !backendApi.ObjectMeta, diff --git a/src/app/frontend/configmapdetail/actionbar.html b/src/app/frontend/configmapdetail/actionbar.html new file mode 100644 index 000000000..5d154b8b8 --- /dev/null +++ b/src/app/frontend/configmapdetail/actionbar.html @@ -0,0 +1,21 @@ + + + + diff --git a/src/app/frontend/configmapdetail/actionbar_controller.js b/src/app/frontend/configmapdetail/actionbar_controller.js new file mode 100644 index 000000000..8055735e2 --- /dev/null +++ b/src/app/frontend/configmapdetail/actionbar_controller.js @@ -0,0 +1,36 @@ +// 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. + +/** + * @final + */ +export class ActionBarController { + /** + * @param {!backendApi.ConfigMapDetail} configMapDetail + * @ngInject + */ + constructor(configMapDetail) { + /** @export {!backendApi.ConfigMapDetail} */ + this.details = configMapDetail; + + /** @export */ + this.i18n = i18n; + } +} + +const i18n = { + /** @export {string} @desc Label 'Config Map' which appears at the top of the + delete dialog, opened from a config map details page. */ + MSG_CONFIG_MAP_DETAIL_CONFIG_MAP_LABEL: goog.getMsg('Config Map'), +}; diff --git a/src/app/frontend/configmapdetail/configmapdetail.html b/src/app/frontend/configmapdetail/configmapdetail.html new file mode 100644 index 000000000..0d18f1fa3 --- /dev/null +++ b/src/app/frontend/configmapdetail/configmapdetail.html @@ -0,0 +1,27 @@ + + +
+ + + + +
{{::value}}
+
+
+
+
diff --git a/src/app/frontend/configmapdetail/configmapdetail_controller.js b/src/app/frontend/configmapdetail/configmapdetail_controller.js new file mode 100644 index 000000000..12744921b --- /dev/null +++ b/src/app/frontend/configmapdetail/configmapdetail_controller.js @@ -0,0 +1,35 @@ +// 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. + +/** + * @final + */ +export class ConfigMapDetailController { + /** + * @param {!backendApi.ConfigMapDetail} configMapDetail + * @ngInject + */ + constructor(configMapDetail) { + /** @export {!backendApi.ConfigMapDetail} */ + this.configMapDetail = configMapDetail; + + /** @export */ + this.i18n = i18n; + } +} + +const i18n = { + /** @export {string} @desc Config map info details section name. */ + MSG_CONFIG_MAP_INFO_DATA_SECTION: goog.getMsg('Data'), +}; diff --git a/src/app/frontend/configmapdetail/configmapdetail_module.js b/src/app/frontend/configmapdetail/configmapdetail_module.js new file mode 100644 index 000000000..f0d5974b5 --- /dev/null +++ b/src/app/frontend/configmapdetail/configmapdetail_module.js @@ -0,0 +1,40 @@ +// 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 chromeModule from 'chrome/chrome_module'; +import componentsModule from 'common/components/components_module'; +import eventsModule from 'events/events_module'; +import filtersModule from 'common/filters/filters_module'; +import stateConfig from './configmapdetail_stateconfig'; +import {configMapInfoComponent} from './configmapinfo_component'; + +/** + * Angular module for the Config Map details view. + * + * The view shows detailed view of a Config Map. + */ +export default angular + .module( + 'kubernetesDashboard.configMapDetail', + [ + 'ngMaterial', + 'ngResource', + 'ui.router', + componentsModule.name, + filtersModule.name, + eventsModule.name, + chromeModule.name, + ]) + .config(stateConfig) + .component('kdConfigMapInfo', configMapInfoComponent); diff --git a/src/app/frontend/configmapdetail/configmapdetail_state.js b/src/app/frontend/configmapdetail/configmapdetail_state.js new file mode 100644 index 000000000..d41241eb7 --- /dev/null +++ b/src/app/frontend/configmapdetail/configmapdetail_state.js @@ -0,0 +1,16 @@ +// 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. + +/** Name of the state. Can be used in, e.g., $state.go method. */ +export const stateName = 'configmapdetail'; diff --git a/src/app/frontend/configmapdetail/configmapdetail_stateconfig.js b/src/app/frontend/configmapdetail/configmapdetail_stateconfig.js new file mode 100644 index 000000000..38e6ff636 --- /dev/null +++ b/src/app/frontend/configmapdetail/configmapdetail_stateconfig.js @@ -0,0 +1,76 @@ +// 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 {actionbarViewName, stateName as chromeStateName} from 'chrome/chrome_state'; +import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_service'; +import {appendDetailParamsToUrl} from 'common/resource/resourcedetail'; +import {stateName as configMapList, stateUrl} from 'configmaplist/configmaplist_state'; + +import {ActionBarController} from './actionbar_controller'; +import {ConfigMapDetailController} from './configmapdetail_controller'; +import {stateName} from './configmapdetail_state'; + +/** + * Configures states for the config map details view. + * + * @param {!ui.router.$stateProvider} $stateProvider + * @ngInject + */ +export default function stateConfig($stateProvider) { + $stateProvider.state(stateName, { + url: appendDetailParamsToUrl(stateUrl), + parent: chromeStateName, + resolve: { + 'configMapDetailResource': getConfigMapDetailResource, + 'configMapDetail': getConfigMapDetail, + }, + data: { + [breadcrumbsConfig]: { + 'label': '{{$stateParams.objectName}}', + 'parent': configMapList, + }, + }, + views: { + '': { + controller: ConfigMapDetailController, + controllerAs: '$ctrl', + templateUrl: 'configmapdetail/configmapdetail.html', + }, + [actionbarViewName]: { + controller: ActionBarController, + controllerAs: '$ctrl', + templateUrl: 'configmapdetail/actionbar.html', + }, + }, + }); +} + +/** + * @param {!./../common/resource/resourcedetail.StateParams} $stateParams + * @param {!angular.$resource} $resource + * @return {!angular.Resource} + * @ngInject + */ +export function getConfigMapDetailResource($resource, $stateParams) { + return $resource(`api/v1/configmap/${$stateParams.objectNamespace}/${$stateParams.objectName}`); +} + +/** + * @param {!angular.Resource} configMapDetailResource + * @return {!angular.$q.Promise} + * @ngInject + */ +export function getConfigMapDetail(configMapDetailResource) { + return configMapDetailResource.get().$promise; +} diff --git a/src/app/frontend/configmapdetail/configmapinfo.html b/src/app/frontend/configmapdetail/configmapinfo.html new file mode 100644 index 000000000..df552d72a --- /dev/null +++ b/src/app/frontend/configmapdetail/configmapinfo.html @@ -0,0 +1,31 @@ + + + + + + + + + + {{::$ctrl.configMap.objectMeta.namespace}} + + + + + + diff --git a/src/app/frontend/configmapdetail/configmapinfo_component.js b/src/app/frontend/configmapdetail/configmapinfo_component.js new file mode 100644 index 000000000..c2421c630 --- /dev/null +++ b/src/app/frontend/configmapdetail/configmapinfo_component.js @@ -0,0 +1,57 @@ +// 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. + +/** + * @final + */ +export default class ConfigMapInfoController { + /** + * Constructs pettion controller info object. + */ + constructor() { + /** + * Config map details. Initialized from the scope. + * @export {!backendApi.ConfigMapDetail} + */ + this.configMap; + + /** @export */ + this.i18n = i18n; + } +} + +/** + * Definition object for the component that displays config map info. + * + * @return {!angular.Directive} + */ +export const configMapInfoComponent = { + controller: ConfigMapInfoController, + templateUrl: 'configmapdetail/configmapinfo.html', + bindings: { + /** {!backendApi.ConfigMapDetail} */ + 'configMap': '=', + }, +}; + +const i18n = { + /** @export {string} @desc Config map info details section name. */ + MSG_CONFIG_MAP_INFO_DETAILS_SECTION: goog.getMsg('Details'), + /** @export {string} @desc Config map info details section name entry. */ + MSG_CONFIG_MAP_INFO_NAME_ENTRY: goog.getMsg('Name'), + /** @export {string} @desc Config map info details section namespace entry. */ + MSG_CONFIG_MAP_INFO_NAMESPACE_ENTRY: goog.getMsg('Namespace'), + /** @export {string} @desc Config map info details section labels entry. */ + MSG_CONFIG_MAP_INFO_LABELS_ENTRY: goog.getMsg('Labels'), +}; diff --git a/src/app/frontend/configmaplist/actionbar.html b/src/app/frontend/configmaplist/actionbar.html new file mode 100644 index 000000000..2c13ca8b7 --- /dev/null +++ b/src/app/frontend/configmaplist/actionbar.html @@ -0,0 +1,17 @@ + + + diff --git a/src/app/frontend/configmaplist/configmapcard.html b/src/app/frontend/configmaplist/configmapcard.html new file mode 100644 index 000000000..cf6ccabdc --- /dev/null +++ b/src/app/frontend/configmaplist/configmapcard.html @@ -0,0 +1,47 @@ + + + + + + + + + + + + {{::$ctrl.configMap.objectMeta.creationTimestamp | relativeTime}} + + {{::$ctrl.getCreatedAtTooltip($ctrl.configMap.objectMeta.creationTimestamp)}} + + + + + + + + + + + + diff --git a/src/app/frontend/configmaplist/configmapcard_component.js b/src/app/frontend/configmaplist/configmapcard_component.js new file mode 100644 index 000000000..0429a6688 --- /dev/null +++ b/src/app/frontend/configmaplist/configmapcard_component.js @@ -0,0 +1,86 @@ +// 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 {StateParams} from 'common/resource/resourcedetail'; +import {stateName} from 'configmapdetail/configmapdetail_state'; + +/** + * Controller for the config map card. + * + * @final + */ +export default class ConfigMapCardController { + /** + * @param {!ui.router.$state} $state + * @param {!angular.$interpolate} $interpolate + * @ngInject + */ + constructor($state, $interpolate) { + /** + * Initialized from the scope. + * @export {!backendApi.ConfigMap} + */ + this.configMap; + + /** @private {!ui.router.$state} */ + this.state_ = $state; + + /** @private */ + this.interpolate_ = $interpolate; + + /** @export */ + this.i18n = i18n; + } + + /** + * @return {string} + * @export + */ + getConfigMapDetailHref() { + return this.state_.href( + stateName, + new StateParams(this.configMap.objectMeta.namespace, this.configMap.objectMeta.name)); + } + + /** + * @export + * @param {string} creationDate - creation date of the config map + * @return {string} localized tooltip with the formated creation date + */ + getCreatedAtTooltip(creationDate) { + let filter = this.interpolate_(`{{date | date:'short'}}`); + /** @type {string} @desc Tooltip 'Created at [some date]' showing the exact creation time of + * config map. */ + let MSG_CONFIG_MAP_LIST_CREATED_AT_TOOLTIP = + goog.getMsg('Created at {$creationDate}', {'creationDate': filter({'date': creationDate})}); + return MSG_CONFIG_MAP_LIST_CREATED_AT_TOOLTIP; + } +} + +/** + * @return {!angular.Component} + */ +export const configMapCardComponent = { + bindings: { + 'configMap': '=', + }, + controller: ConfigMapCardController, + templateUrl: 'configmaplist/configmapcard.html', +}; + +const i18n = { + /** @export {string} @desc Label 'Config Map' which will appear in the config map + delete dialog opened from a config map card on the list page. */ + MSG_CONFIG_MAP_LIST_CONFIG_MAP_LABEL: goog.getMsg('Config Map'), +}; diff --git a/src/app/frontend/configmaplist/configmapcardlist.html b/src/app/frontend/configmaplist/configmapcardlist.html new file mode 100644 index 000000000..a12748225 --- /dev/null +++ b/src/app/frontend/configmaplist/configmapcardlist.html @@ -0,0 +1,38 @@ + + + + + + {{::$ctrl.i18n.MSG_CONFIG_MAP_LIST_HEADER_NAME}} + + + {{::$ctrl.i18n.MSG_CONFIG_MAP_LIST_HEADER_LABELS}} + + + {{::$ctrl.i18n.MSG_CONFIG_MAP_LIST_HEADER_AGE}} + + + + + + + + + + + diff --git a/src/app/frontend/configmaplist/configmapcardlist_component.js b/src/app/frontend/configmaplist/configmapcardlist_component.js new file mode 100644 index 000000000..57738e8d5 --- /dev/null +++ b/src/app/frontend/configmaplist/configmapcardlist_component.js @@ -0,0 +1,49 @@ +// 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. + +/** + * Controller for config map card list. + * + * @final + */ +export class ConfigMapCardListController { + /** + * @ngInject + */ + constructor() { + /** @export */ + this.i18n = i18n; + } +} + +/** + * @return {!angular.Component} + */ +export const configMapCardListComponent = { + transclude: true, + controller: ConfigMapCardListController, + bindings: { + 'configMapList': '<', + }, + templateUrl: 'configmaplist/configmapcardlist.html', +}; + +const i18n = { + /** @export {string} @desc Pet set list header: name. */ + MSG_CONFIG_MAP_LIST_HEADER_NAME: goog.getMsg('Name'), + /** @export {string} @desc Pet set list header: labels. */ + MSG_CONFIG_MAP_LIST_HEADER_LABELS: goog.getMsg('Labels'), + /** @export {string} @desc Pet set list header: age. */ + MSG_CONFIG_MAP_LIST_HEADER_AGE: goog.getMsg('Age'), +}; diff --git a/src/app/frontend/configmaplist/configmaplist.html b/src/app/frontend/configmaplist/configmaplist.html new file mode 100644 index 000000000..71125b71c --- /dev/null +++ b/src/app/frontend/configmaplist/configmaplist.html @@ -0,0 +1,23 @@ + + + + + + + + + diff --git a/src/app/frontend/configmaplist/configmaplist_controller.js b/src/app/frontend/configmaplist/configmaplist_controller.js new file mode 100644 index 000000000..d6fb82bc3 --- /dev/null +++ b/src/app/frontend/configmaplist/configmaplist_controller.js @@ -0,0 +1,35 @@ +// 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. + +/** + * Controller for the config map list view. + * + * @final + */ +export class ConfigMapListController { + /** + * @param {!backendApi.ConfigMapList} configMapList + * @ngInject + */ + constructor(configMapList) { + /** @export {!backendApi.ConfigMapList} */ + this.configMapList = configMapList; + } + + /** + * @return {boolean} + * @export + */ + shouldShowZeroState() { return this.configMapList.items.length === 0; } +} diff --git a/src/app/frontend/configmaplist/configmaplist_module.js b/src/app/frontend/configmaplist/configmaplist_module.js new file mode 100644 index 000000000..10bb1835b --- /dev/null +++ b/src/app/frontend/configmaplist/configmaplist_module.js @@ -0,0 +1,40 @@ +// 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 stateConfig from './configmaplist_stateconfig'; +import filtersModule from 'common/filters/filters_module'; +import componentsModule from 'common/components/components_module'; +import chromeModule from 'chrome/chrome_module'; +import configMapDetailModule from 'configmapdetail/configmapdetail_module'; +import {configMapCardComponent} from './configmapcard_component'; +import {configMapCardListComponent} from './configmapcardlist_component'; + +/** + * Angular module for the Config Map list view. + */ +export default angular + .module( + 'kubernetesDashboard.configMapList', + [ + 'ngMaterial', + 'ngResource', + 'ui.router', + filtersModule.name, + componentsModule.name, + configMapDetailModule.name, + chromeModule.name, + ]) + .config(stateConfig) + .component('kdConfigMapCardList', configMapCardListComponent) + .component('kdConfigMapCard', configMapCardComponent); diff --git a/src/app/frontend/configmaplist/configmaplist_state.js b/src/app/frontend/configmaplist/configmaplist_state.js new file mode 100644 index 000000000..8d8beaf10 --- /dev/null +++ b/src/app/frontend/configmaplist/configmaplist_state.js @@ -0,0 +1,19 @@ +// 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. + +/** Name of the state. Can be used in, e.g., $state.go method. */ +export const stateName = 'configmap'; + +/** Absolute URL of the state. */ +export const stateUrl = '/configmap'; diff --git a/src/app/frontend/configmaplist/configmaplist_stateconfig.js b/src/app/frontend/configmaplist/configmaplist_stateconfig.js new file mode 100644 index 000000000..557469807 --- /dev/null +++ b/src/app/frontend/configmaplist/configmaplist_stateconfig.js @@ -0,0 +1,69 @@ +// 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 {actionbarViewName, stateName as chromeStateName} from 'chrome/chrome_state'; +import {breadcrumbsConfig} from 'common/components/breadcrumbs/breadcrumbs_service'; +import {stateName as workloadsState} from 'workloads/workloads_state'; + +import {ConfigMapListController} from './configmaplist_controller'; +import {stateName, stateUrl} from './configmaplist_state'; + +/** + * Configures states for the config map list view. + * + * @param {!ui.router.$stateProvider} $stateProvider + * @ngInject + */ +export default function stateConfig($stateProvider) { + $stateProvider.state(stateName, { + url: stateUrl, + parent: chromeStateName, + resolve: { + 'configMapList': resolveConfigMapList, + }, + data: { + [breadcrumbsConfig]: { + 'label': i18n.MSG_BREADCRUMBS_CONFIG_MAPS_LABEL, + 'parent': workloadsState, + }, + }, + views: { + '': { + controller: ConfigMapListController, + controllerAs: '$ctrl', + templateUrl: 'configmaplist/configmaplist.html', + }, + [actionbarViewName]: { + templateUrl: 'configmaplist/actionbar.html', + }, + }, + }); +} + +/** + * @param {!angular.$resource} $resource + * @param {!./../chrome/chrome_state.StateParams} $stateParams + * @return {!angular.$q.Promise} + * @ngInject + */ +export function resolveConfigMapList($resource, $stateParams) { + /** @type {!angular.Resource} */ + let resource = $resource(`api/v1/configmap/${$stateParams.namespace || ''}`); + return resource.get().$promise; +} + +const i18n = { + /** @type {string} @desc Label 'Config Maps' that appears as a breadcrumbs on the action bar. */ + MSG_BREADCRUMBS_CONFIG_MAPS_LABEL: goog.getMsg('Config Maps'), +}; diff --git a/src/app/frontend/index_module.js b/src/app/frontend/index_module.js index 185445c7b..756c2496b 100644 --- a/src/app/frontend/index_module.js +++ b/src/app/frontend/index_module.js @@ -34,6 +34,8 @@ import serviceListModule from './servicelist/servicelist_module'; import workloadsModule from './workloads/workloads_module'; import podDetailModule from './poddetail/poddetail_module'; import petSetListModule from './petsetlist/petsetlist_module'; +import configMapListModule from './configmaplist/configmaplist_module'; +import configMapDetailModule from './configmapdetail/configmapdetail_module'; export default angular .module( @@ -62,6 +64,8 @@ export default angular serviceListModule.name, podDetailModule.name, petSetListModule.name, + configMapListModule.name, + configMapDetailModule.name, ]) .config(indexConfig) .config(routeConfig); diff --git a/src/test/frontend/configmapdetail/actionbar_controller_test.js b/src/test/frontend/configmapdetail/actionbar_controller_test.js new file mode 100644 index 000000000..ad22a0965 --- /dev/null +++ b/src/test/frontend/configmapdetail/actionbar_controller_test.js @@ -0,0 +1,31 @@ +// 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 {ActionBarController} from 'configmapdetail/actionbar_controller'; +import module from 'configmapdetail/configmapdetail_module'; + +describe('Action Bar controller', () => { + /** @type {!ActionBarController} */ + let ctrl; + let details = {}; + + beforeEach(() => { + angular.mock.module(module.name); + + angular.mock.inject( + ($controller) => { ctrl = $controller(ActionBarController, {configMapDetail: details}); }); + }); + + it('should initialize details', () => { expect(ctrl.details).toBe(details); }); +}); diff --git a/src/test/frontend/configmapdetail/configmapdetail_controller_test.js b/src/test/frontend/configmapdetail/configmapdetail_controller_test.js new file mode 100644 index 000000000..cf68eaf0f --- /dev/null +++ b/src/test/frontend/configmapdetail/configmapdetail_controller_test.js @@ -0,0 +1,29 @@ +// 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 {ConfigMapDetailController} from 'configmapdetail/configmapdetail_controller'; +import configMapDetailModule from 'configmapdetail/configmapdetail_module'; + +describe('Config Map Detail controller', () => { + + beforeEach(() => { angular.mock.module(configMapDetailModule.name); }); + + it('should initialize config map controller', angular.mock.inject(($controller) => { + let data = {}; + /** @type {!ConfigMapDetailController} */ + let ctrl = $controller(ConfigMapDetailController, {configMapDetail: data}); + + expect(ctrl.configMapDetail).toBe(data); + })); +}); diff --git a/src/test/frontend/configmapdetail/configmapinfo_component_test.js b/src/test/frontend/configmapdetail/configmapinfo_component_test.js new file mode 100644 index 000000000..da86976dd --- /dev/null +++ b/src/test/frontend/configmapdetail/configmapinfo_component_test.js @@ -0,0 +1,34 @@ +// 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 configMapDetailModule from 'configmapdetail/configmapdetail_module'; + +describe('Config Map Info controller', () => { + /** @type {!ConfigMapInfoController} */ + let ctrl; + + beforeEach(() => { + angular.mock.module(configMapDetailModule.name); + + angular.mock.inject(($componentController, $rootScope) => { + ctrl = $componentController('kdConfigMapInfo', {$scope: $rootScope}, { + configMap: { + data: {foo: 'bar'}, + }, + }); + }); + }); + + it('should initialize the ctrl', () => { expect(ctrl.i18n).not.toBeUndefined(); }); +}); diff --git a/src/test/frontend/configmaplist/configmapcard_component_test.js b/src/test/frontend/configmaplist/configmapcard_component_test.js new file mode 100644 index 000000000..2759fa161 --- /dev/null +++ b/src/test/frontend/configmaplist/configmapcard_component_test.js @@ -0,0 +1,41 @@ +// 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 configMapListModule from 'configmaplist/configmaplist_module'; + +describe('Config Map card', () => { + /** @type {!configmaplist/configmapcard_component.ConfigMapCardController} */ + let ctrl; + + beforeEach(() => { + angular.mock.module(configMapListModule.name); + + angular.mock.inject(($componentController, $rootScope) => { + ctrl = $componentController('kdConfigMapCard', {$scope: $rootScope}); + }); + }); + + it('should get details href', () => { + ctrl.configMap = { + objectMeta: { + namespace: 'foo', + name: 'bar', + }, + }; + expect(ctrl.getConfigMapDetailHref()).toBe('#/configmap/foo/bar'); + }); + + it('should format the "created at" tooltip correctly', () => { + expect(ctrl.getCreatedAtTooltip('2016-06-06T09:13:12Z')).toMatch('Created at 6/6/16.*'); + }); +}); diff --git a/src/test/frontend/configmaplist/configmapcardlist_component_test.js b/src/test/frontend/configmaplist/configmapcardlist_component_test.js new file mode 100644 index 000000000..270f1cf0f --- /dev/null +++ b/src/test/frontend/configmaplist/configmapcardlist_component_test.js @@ -0,0 +1,29 @@ +// 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 configMapListModule from 'configmaplist/configmaplist_module'; + +describe('Config Map card list', () => { + /** @type {!configmaplist/configmapcard_component.ConfigMapCardListController} */ + let ctrl; + + beforeEach(() => { + angular.mock.module(configMapListModule.name); + + angular.mock.inject(($componentController, $rootScope) => { + ctrl = $componentController('kdConfigMapCardList', {$scope: $rootScope}); + }); + }); + + it('should init i18n', () => { expect(ctrl.i18n).not.toBeUndefined(); }); +}); diff --git a/src/test/frontend/configmaplist/configmaplist_controller_test.js b/src/test/frontend/configmaplist/configmaplist_controller_test.js new file mode 100644 index 000000000..17d9686a4 --- /dev/null +++ b/src/test/frontend/configmaplist/configmaplist_controller_test.js @@ -0,0 +1,47 @@ +// 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 {ConfigMapListController} from 'configmaplist/configmaplist_controller'; +import configMapListModule from 'configmaplist/configmaplist_module'; + +describe('Config Map list controller', () => { + /** @type {!configmaplist/configmaplist_controller.ConfigMapListController} */ + let ctrl; + + beforeEach(() => { + angular.mock.module(configMapListModule.name); + + angular.mock.inject(($controller) => { + ctrl = $controller(ConfigMapListController, {configMapList: {items: []}}); + }); + }); + + it('should initialize config map controller', angular.mock.inject(($controller) => { + let ctrls = {}; + /** @type {!ConfigMapListController} */ + let ctrl = $controller(ConfigMapListController, {configMapList: {items: ctrls}}); + + expect(ctrl.configMapList.items).toBe(ctrls); + })); + + it('should show zero state', () => { expect(ctrl.shouldShowZeroState()).toBe(true); }); + + it('should hide zero state', () => { + // given + ctrl.configMapList = {items: ['mock']}; + + // then + expect(ctrl.shouldShowZeroState()).toBe(false); + }); +}); diff --git a/src/test/frontend/configmaplist/configmaplist_stateconfig_test.js b/src/test/frontend/configmaplist/configmaplist_stateconfig_test.js new file mode 100644 index 000000000..e2a1af55c --- /dev/null +++ b/src/test/frontend/configmaplist/configmaplist_stateconfig_test.js @@ -0,0 +1,44 @@ +// 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 configMapListModule from 'configmaplist/configmaplist_module'; +import {resolveConfigMapList} from 'configmaplist/configmaplist_stateconfig'; + +describe('StateConfig for config map controller list', () => { + beforeEach(() => { angular.mock.module(configMapListModule.name); }); + + it('should resolve config map list with namespace', angular.mock.inject(($q) => { + let promise = $q.defer().promise; + + let resource = jasmine.createSpy('$resource'); + resource.and.returnValue({get: function() { return {$promise: promise}; }}); + + let actual = resolveConfigMapList(resource, {}); + + expect(resource).toHaveBeenCalledWith('api/v1/configmap/'); + expect(actual).toBe(promise); + })); + + it('should resolve config map list with no namespace', angular.mock.inject(($q) => { + let promise = $q.defer().promise; + + let resource = jasmine.createSpy('$resource'); + resource.and.returnValue({get: function() { return {$promise: promise}; }}); + + let actual = resolveConfigMapList(resource, {namespace: 'foo'}); + + expect(resource).toHaveBeenCalledWith('api/v1/configmap/foo'); + expect(actual).toBe(promise); + })); +}); -- GitLab