提交 5f863140 编写于 作者: M Marcin Maciaszczyk 提交者: GitHub

Refactor logs view (#1229)

* Refactor logs view

* Make logs view full width & height

* Refactor logs view
上级 14579751
......@@ -792,4 +792,7 @@
<translation id="1052756257716282729" key="MSG_DAEMON_SET_LIST_MEMORY_GRAPH_CARD_TITLE" source="/usr/local/google/home/pdabkowski/WebstormProjects/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Title for graph card displaying memory metric of daemon sets.">Memory usage history</translation>
<translation id="1611578389032486450" key="MSG_WORKLOADS_CPU_GRAPH_CARD_TITLE" source="/usr/local/google/home/pdabkowski/WebstormProjects/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Title for graph card displaying CPU metric of one all resources.">CPU usage history</translation>
<translation id="2764620581378008580" key="MSG_WORKLOADS_MEMORY_GRAPH_CARD_TITLE" source="/usr/local/google/home/pdabkowski/WebstormProjects/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Title for graph card displaying memory metric of one all resources.">Memory usage history</translation>
<translation id="173829199104422763" key="MSG_LOGS_TITLE_FROM" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="Title prefix for logs card.">Logs from</translation>
<translation id="545013982201122635" key="MSG_LOGS_TITLE_IN" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="Title part for logs card.">in</translation>
<translation id="9015703491006359663" key="MSG_LOGS_TITLE_TO" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="Footer part for logs card.">to</translation>
</translationbundle>
\ No newline at end of file
......@@ -985,4 +985,16 @@
<translation id="1052756257716282729" key="MSG_DAEMON_SET_LIST_MEMORY_GRAPH_CARD_TITLE" source="/usr/local/google/home/pdabkowski/WebstormProjects/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Title for graph card displaying memory metric of daemon sets.">メモリー使用量の履歴</translation>
<translation id="1611578389032486450" key="MSG_WORKLOADS_CPU_GRAPH_CARD_TITLE" source="/usr/local/google/home/pdabkowski/WebstormProjects/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Title for graph card displaying CPU metric of one all resources.">CPU使用量の履歴</translation>
<translation id="2764620581378008580" key="MSG_WORKLOADS_MEMORY_GRAPH_CARD_TITLE" source="/usr/local/google/home/pdabkowski/WebstormProjects/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Title for graph card displaying memory metric of one all resources.">メモリー使用量の履歴</translation>
<translation id="4466763630197200161" key="MSG_BREADCRUMBS_ADMIN_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label 'Admin' that appears as a breadcrumbs on the action bar.">Admin</translation>
<translation id="1459282068813879241" key="MSG_ADMIN_NAMESPACES_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Namespaces</translation>
<translation id="133343695009872751" key="MSG_ADMIN_NODES_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Nodes</translation>
<translation id="6870889542203892242" key="MSG_ADMIN_PERSISTENT_VOLUMES_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Persistent Volumes</translation>
<translation id="3195481899172694103" key="MSG_ACTION_BAR_CREATE_ACTION" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label for global action bar create button.">Create</translation>
<translation id="6165413233411120289" key="MSG_ACTION_BAR_CREATE_ACTION_TOOLTIP" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label for global action bar create button tooltip.">Create an application or any Kubernetes resource</translation>
<translation id="5207082267245498149" key="MSG_BREADCRUMBS_SERVICES_AND_DISCOVERY_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label 'Services and discovery' that appears as a breadcrumbs on the action bar.">Services and discovery</translation>
<translation id="352791570684627676" key="MSG_SERVICES_AND_DISCOVERY_INGRESS_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Ingress</translation>
<translation id="6306881076646050049" key="MSG_SERVICES_AND_DISCOVERY_SERVICES_LABEL" source="/usr/local/google/home/bryk/src/github.com/kubernetes/dashboard/.tmp/serve/app-dev.js" desc="Label that appears above the list of resources.">Services</translation>
<translation id="173829199104422763" key="MSG_LOGS_TITLE_FROM" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="Title prefix for logs card.">Logs from</translation>
<translation id="545013982201122635" key="MSG_LOGS_TITLE_IN" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="Title part for logs card.">in</translation>
<translation id="9015703491006359663" key="MSG_LOGS_TITLE_TO" source="/home/maciaszczykm/workspace/dashboard/.tmp/serve/app-dev.js" desc="Footer part for logs card.">to</translation>
</translationbundle>
\ No newline at end of file
......@@ -774,6 +774,13 @@ backendApi.NamespaceSpec;
*/
backendApi.PodContainer;
/**
* @typedef {{
* containers: !Array<string>
* }}
*/
backendApi.PodContainerList;
/**
* @typedef {{
* name: string,
......
......@@ -22,6 +22,7 @@
$display-4-font-size-base: rem(11.2) !default;
$display-1-font-size-base: rem(3.4) !default;
$headline-font-size-base: rem(2.4) !default;
$title-font-size-base: rem(2) !default;
$subhead-font-size-base-lg: rem(1.8) !default;
$subhead-font-size-base: rem(1.6) !default;
$body-font-size-base: rem(1.4) !default;
......
......@@ -38,7 +38,7 @@ limitations under the License.
</md-progress-circular>
</div>
<div ng-switch-when="false" class="kd-app-content">
<div ui-view class="md-body-1"></div>
<div ui-view class="md-body-1 kd-content-div"></div>
</div>
</div>
</md-content>
......
......@@ -51,6 +51,7 @@
body,
.kd-app-content {
background-color: $body;
height: 100%;
max-height: 100%;
}
......
......@@ -29,7 +29,7 @@ export default function stateConfig($stateProvider) {
abstract: true,
views: {
'': {
template: '<div ui-view></div>',
template: '<div ui-view class="kd-content-div"></div>',
},
[toolbarViewName]: {
template: `<div ui-view="${toolbarViewName}"></div>`,
......
......@@ -19,6 +19,7 @@ limitations under the License.
<h1 ng-if="$ctrl.isTitleSlotFilled()" layout-padding
class="kd-content-card-content-title md-title"
ng-transclude="title"></h1>
<div ng-transclude="content"></div>
<div ng-transclude="content" class="kd-content-card-transclude-content"></div>
<div class="kd-content-card-content-footer" ng-transclude="footer"></div>
</div>
</div>
......@@ -21,10 +21,13 @@
kd-content-card {
display: block;
height: 100%;
margin: 2.5 * $baseline-grid;
}
.kd-content-card {
height: 100%;
kd-content {
&.kd-content-padded {
display: block;
......@@ -48,3 +51,9 @@ kd-content-card {
}
}
}
.kd-content-card-content-footer {
border-top: 1px solid $border;
box-sizing: border-box;
margin: 0;
}
......@@ -38,6 +38,7 @@ export class ContentCardController {
* <kd-content-card>
* <kd-title>My Title</kd-title>
* <kd-content>My Content</kd-content>
* <kd-footer>My Footer</kd-footer>
* </kd-content-card>
*
* @type {!angular.Component}
......@@ -48,5 +49,6 @@ export const contentCardComponent = {
transclude: /** @type {undefined} TODO(bryk): Remove this when externs are fixed */ ({
'title': '?kdTitle',
'content': '?kdContent',
'footer': '?kdFooter',
}),
};
......@@ -14,40 +14,64 @@ See the License for the specific language governing permissions and
limitations under the License.
-->
<kd-logs-toolbar containers="ctrl.podContainers.containers"></kd-logs-toolbar>
<div>
<span ng-show="ctrl.logsSet.length > 1"> Showing logs from {{ctrl.podLogs.firstLogLineReference.logTimestamp | date : "medium" }} to {{ctrl.podLogs.lastLogLineReference.logTimestamp | date : "medium" }}</span>
<div class="kd-list-pagination-buttons">
<md-button class="md-icon-button md-button md-ink-ripple"
ng-click="ctrl.loadOldest()">
<md-icon>first_page</md-icon>
</md-button>
<md-button class="md-icon-button md-button md-ink-ripple"
ng-click="ctrl.loadOlder()">
<md-icon>chevron_left</md-icon>
</md-button>
<md-button class="md-icon-button md-button md-ink-ripple"
ng-click="ctrl.loadNewer()">
<md-icon>chevron_right</md-icon>
</md-button>
<md-button class="md-icon-button md-button md-ink-ripple"
ng-click="ctrl.loadNewest()">
<md-icon>last_page</md-icon>
</md-button>
</div>
</div>
<kd-content-card>
<kd-content-card class="kd-log-content-card">
<kd-title class="kd-logs-title">
{{ctrl.i18n.MSG_LOGS_TITLE_FROM}}
<md-select class="kd-logs-toolbar-select" ng-model="ctrl.container"
md-on-close="ctrl.onContainerChange(ctrl.container)" required>
<md-option ng-repeat="item in ctrl.containers" ng-value="item">
<span class="kd-logs-toolbar-text">{{::item}}</span>
</md-option>
</md-select>
{{ctrl.i18n.MSG_LOGS_TITLE_IN}} {{ctrl.podLogs.podId}}
<div class="kd-logs-style-buttons">
<md-button class="kd-logs-toolbar-button" ng-click="ctrl.onTextColorChange()">
<md-icon md-font-library="material-icons" ng-class="ctrl.getColorIconClass()">
format_color_text
</md-icon>
</md-button>
<md-button class="kd-logs-toolbar-button" ng-click="ctrl.onFontSizeChange()">
<md-icon md-font-library="material-icons" ng-class="ctrl.getSizeIconClass()">
text_fields
</md-icon>
</md-button>
</div>
</kd-title>
<kd-content>
<md-virtual-repeat-container class="log-view" ng-class="ctrl.getStyleClass()">
<md-virtual-repeat-container class="kd-log-view" ng-class="ctrl.getStyleClass()"
md-top-index="ctrl.topIndex">
<div md-virtual-repeat="item in ctrl.logsSet" ng-class="ctrl.getLogsClass()">
{{item}}
<span ng-bind-html="item">&nbsp;</span>
</div>
</md-virtual-repeat-container>
</kd-content>
<kd-footer ng-show="ctrl.logsSet.length > 1">
<div layout="row">
<span class="kd-logs-info">
{{ctrl.i18n.MSG_LOGS_TITLE_FROM}}
{{ctrl.podLogs.firstLogLineReference.logTimestamp | date : "short"}}
{{ctrl.i18n.MSG_LOGS_TITLE_TO}}
{{ctrl.podLogs.lastLogLineReference.logTimestamp | date : "short" }}
</span>
<span flex></span>
<div class="kd-list-pagination-buttons">
<md-button class="md-icon-button md-button md-ink-ripple"
ng-click="ctrl.loadOldest()">
<md-icon>first_page</md-icon>
</md-button>
<md-button class="md-icon-button md-button md-ink-ripple"
ng-click="ctrl.loadOlder()">
<md-icon>chevron_left</md-icon>
</md-button>
<md-button class="md-icon-button md-button md-ink-ripple"
ng-click="ctrl.loadNewer()">
<md-icon>chevron_right</md-icon>
</md-button>
<md-button class="md-icon-button md-button md-ink-ripple"
ng-click="ctrl.loadNewest()">
<md-icon>last_page</md-icon>
</md-button>
</div>
</div>
</kd-footer>
</kd-content-card>
......@@ -49,7 +49,88 @@ $logs-color-white: #fff;
font-size: $caption-font-size-base;
}
.log-view {
height: 800px;
.kd-log-view {
flex: 1;
font-family: $font-family-medium-monospace;
white-space: pre-wrap;
width: 100%;
}
// The style below is to make the logs view card full width & height.
kd-content-card {
&.kd-log-content-card {
box-sizing: border-box;
height: 100%;
margin: 0;
padding: 2.5 * $baseline-grid;
.kd-content-card {
height: 100%;
.kd-content-card-transclude-content {
display: flex;
flex: 1;
kd-content {
display: flex;
flex: 1;
}
}
}
.kd-content-card-content {
display: flex;
flex-direction: column;
height: 100%;
}
}
}
.kd-logs-toolbar-select {
display: inline-flex;
margin: 0;
.md-select-value {
font-size: $title-font-size-base;
min-width: 20 * $baseline-grid;
}
&:not([disabled]) {
&:focus {
.md-select-value {
color: $foreground-1;
}
}
}
}
.kd-logs-toolbar-button {
min-width: unset;
}
.kd-logs-color-icon {
background-color: $logs-color-black;
color: $logs-color-white;
}
.kd-logs-color-icon-invert {
background-color: $logs-color-white;
color: $logs-color-black;
}
.kd-logs-size-icon {
color: $logs-color-black;
}
.kd-logs-size-icon-compact {
color: $logs-color-black;
transform: scale(-1, 1);
}
.kd-logs-info {
padding: 1.5 * $baseline-grid;
}
.kd-logs-style-buttons {
float: right;
}
......@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import {stateName as logs, StateParams} from './logs_state';
const logsPerView = 100;
const maxLogSize = 2e9;
......@@ -23,15 +24,17 @@ const maxLogSize = 2e9;
export class LogsController {
/**
* @param {!backendApi.Logs} podLogs
* @param {!angular.Resource<!backendApi.PodContainerList>} podContainers
* @param {!backendApi.PodContainerList} podContainers
* @param {!./logs_service.LogsService} logsService
* @param {!angular.$sce} $sce
* @param {!angular.$document} $document
* @param {!./logs_state.StateParams} $stateParams
* @param {!angular.$resource} $resource
* @param {!ui.router.$state} $state
* @ngInject
*/
constructor(podLogs, podContainers, logsService, $sce, $document, $resource, $stateParams) {
constructor(
podLogs, podContainers, logsService, $sce, $document, $resource, $stateParams, $state) {
/** @private {!angular.$sce} */
this.sce_ = $sce;
......@@ -47,9 +50,6 @@ export class LogsController {
/** @export {!./logs_service.LogsService} */
this.logsService = logsService;
/** @export {!angular.Resource<!backendApi.PodContainerList>} */
this.podContainers = podContainers;
/** @export */
this.i18n = i18n;
......@@ -61,9 +61,24 @@ export class LogsController {
/** @private {!backendApi.LogViewInfo}*/
this.currentLogView;
/** @private {!ui.router.$state} */
this.state_ = $state;
/** @export {!Array<string>} */
this.containers = podContainers.containers;
/** @export {string} */
this.container = this.podLogs.container;
/** @export {number} */
this.topIndex = 0;
}
$onInit() { this.loadLogs(this.podLogs); }
$onInit() {
this.loadLogs(this.podLogs);
this.topIndex = this.podLogs.logs.length;
}
/**
* Updates all state parameters and sets the current log view to podLogs. If logs are not
......@@ -162,6 +177,32 @@ export class LogsController {
return logsTextColor;
}
/**
* Return proper style class for text color icon.
* @export
* @returns {string}
*/
getColorIconClass() {
const logsTextColor = 'kd-logs-color-icon';
if (this.logsService.getInverted()) {
return `${logsTextColor}-invert`;
}
return logsTextColor;
}
/**
* Return proper style class for font size icon.
* @export
* @returns {string}
*/
getSizeIconClass() {
const logsTextColor = 'kd-logs-size-icon';
if (this.logsService.getCompact()) {
return `${logsTextColor}-compact`;
}
return logsTextColor;
}
/**
* Formats logs as HTML.
*
......@@ -199,9 +240,77 @@ export class LogsController {
div.appendChild(this.document_.createTextNode(html));
return div.innerHTML;
}
/**
* Execute a code when a user changes the selected option of a container element.
* @param {string} container
* @export
*/
onContainerChange(container) {
this.state_.go(
logs, new StateParams(
this.stateParams_.objectNamespace, this.stateParams_.objectName, container));
}
/**
* Execute a code when a user changes the selected option for console font size.
* @export
*/
onFontSizeChange() { this.logsService.setCompact(); }
/**
* Execute a code when a user changes the selected option for console color.
* @export
*/
onTextColorChange() { this.logsService.setInverted(); }
/**
* Find Pod by name.
* Return object or undefined if can not find a object.
* @param {!Array<!backendApi.ReplicationControllerPodWithContainers>} array
* @param {!string} name
* @return {!backendApi.ReplicationControllerPodWithContainers|undefined}
* @private
*/
findPodByName_(array, name) {
for (let i = 0; i < array.length; i++) {
if (array[i].name === name) {
return array[i];
}
}
return undefined;
}
/**
* Find Container by name.
* Return object or undefined if can not find a object.
* @param {!Array<!backendApi.PodContainer>} array
* @param {string} name
* @return {!backendApi.PodContainer}
* @private
*/
initializeContainer_(array, name) {
let container = undefined;
for (let i = 0; i < array.length; i++) {
if (array[i].name === name) {
container = array[i];
break;
}
}
if (!container) {
container = array[0];
}
return container;
}
}
const i18n = {
/** @export {string} @desc Title prefix for logs card. */
MSG_LOGS_TITLE_FROM: goog.getMsg('Logs from'),
/** @export {string} @desc Title part for logs card. */
MSG_LOGS_TITLE_IN: goog.getMsg('in'),
/** @export {string} @desc Footer part for logs card. */
MSG_LOGS_TITLE_TO: goog.getMsg('to'),
/** @export {string} @desc Title for logs card zerostate in logs page. */
MSG_LOGS_ZEROSTATE_TITLE: goog.getMsg('There is nothing to display here'),
/** @export {string} @desc Text for logs card zerostate in logs page. */
......
......@@ -14,8 +14,6 @@
import {LogsService} from './logs_service';
import stateConfig from './logs_stateconfig';
import {logsToolbarComponent} from './logstoolbar/logstoolbar_controller';
/**
* Angular module for the logs view.
......@@ -29,5 +27,4 @@ export default angular
'ui.router',
])
.service('logsService', LogsService)
.config(stateConfig)
.component('kdLogsToolbar', logsToolbarComponent);
.config(stateConfig);
<!--
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.
-->
<div layout="row" layout-margin layout-align="center center" class="kd-logs-toolbar">
<div class="kd-logs-toolbar-text" flex="none">
<span>{{::ctrl.i18n.MSG_LOGS_POD_LABEL}}</span>
</div>
<div class="kd-logs-toolbar-text" flex="shrink">
<kd-middle-ellipsis display-string="{{::ctrl.stateParams.objectName}}">
</kd-middle-ellipsis>
</div>
<span class="kd-logs-toolbar-text">{{::ctrl.i18n.MSG_LOGS_CONTAINER_LABEL}}</span>
<md-select class="kd-logs-toolbar-select" aria-label="Containers" ng-model="ctrl.container"
md-on-close="ctrl.onContainerChange(ctrl.container)"
required>
<md-option ng-repeat="item in ctrl.containers" ng-value="item">
<span class="kd-logs-toolbar-text">{{::item}}</span>
</md-option>
</md-select>
<span flex="auto"></span>
<md-button class="kd-logs-toolbar-button" ng-click="ctrl.onTextColorChange()">
<md-icon md-font-library="material-icons" ng-class="ctrl.getColorIconClass()">
format_color_text
</md-icon>
</md-button>
<md-button class="kd-logs-toolbar-button" ng-click="ctrl.onFontSizeChange()">
<md-icon md-font-library="material-icons" ng-class="ctrl.getSizeIconClass()">
text_fields
</md-icon>
</md-button>
</div>
// 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 '../../variables';
$logs-toolbar-color-black: #000;
$logs-toolbar-color-white: #fff;
.kd-logs-color-icon {
background-color: $logs-toolbar-color-black;
color: $logs-toolbar-color-white;
}
.kd-logs-color-icon-invert {
background-color: $logs-toolbar-color-white;
color: $logs-toolbar-color-black;
}
md-toolbar {
md-icon {
// This override styles to get flipped size icon on toolbar
&.kd-logs-size-icon-compact {
transform: scale(-1, 1);
}
// This override styles to get white-black icon on toolbar
&.kd-logs-color-icon-invert {
color: $logs-toolbar-color-black;
}
}
}
.kd-logs-toolbar-text {
font-size: $subhead-font-size-base;
}
.kd-logs-toolbar-select {
margin-bottom: 2 * $baseline-grid;
margin-left: auto;
&:not([disabled]) {
&:focus {
.md-select-value {
color: $logs-toolbar-color-white;
}
}
}
// Fixes pickers placement issue on Internet Explorer. It's caused by Angular Material
// stylesheets, which apply 'transform: translate3d(0, 2px, 0)' on 'md-select-value' elements.
.md-select-value {
.kd-logs-toolbar-text {
-ms-transform: translateY(-1px);
}
}
}
.kd-slider {
display: inline-block;
margin-bottom: - $baseline-grid / 2;
max-width: 15 * $baseline-grid;
min-width: 15 * $baseline-grid;
}
.kd-logs-toolbar-button {
min-width: unset;
}
.kd-logs-toolbar-menu-button {
color: $content-background;
&::after {
content: '\25BC';
display: inline-block;
position: relative;
transform: scaleY(.9) scaleX(1.3);
}
}
.kd-logs-toolbar-menu-bar {
.kd-logs-toolbar-menu-button {
background: none;
}
}
.kd-logs-toolbar {
margin-bottom: $baseline-grid / 2;
}
// 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 {stateName as logs, StateParams} from './../logs_state';
/**
* Controller for the logs view.
* @final
*/
export default class LogsToolbarController {
/**
* @param {!ui.router.$state} $state
* @param {!StateParams} $stateParams
* @param {!../logs_service.LogsService} logsService
* @ngInject
*/
constructor($state, $stateParams, logsService) {
/** @private {!ui.router.$state} */
this.state_ = $state;
/** @export {../logs_state.StateParams} */
this.stateParams = $stateParams;
/**
* Initialised from scope.
* @private {!../logs_service.LogsService}
*/
this.logsService = logsService;
/** @export {!Array<string>} Initialised from scope. */
this.containers;
/** @export {string} */
this.container = $stateParams.container || this.containers[0];
/** @export */
this.i18n = i18n;
}
/**
* Execute a code when a user changes the selected option of a container element.
* @param {string} container
* @export
*/
onContainerChange(container) {
this.state_.go(
logs,
new StateParams(this.stateParams.objectNamespace, this.stateParams.objectName, container));
}
/**
* Return proper style class for text color icon.
* @export
* @returns {string}
*/
getColorIconClass() {
const logsTextColor = 'kd-logs-color-icon';
if (this.logsService.getInverted()) {
return `${logsTextColor}-invert`;
} else {
return logsTextColor;
}
}
/**
* Return proper style class for font size icon.
* @export
* @returns {string}
*/
getSizeIconClass() {
const logsTextColor = 'kd-logs-size-icon';
if (this.logsService.getCompact()) {
return `${logsTextColor}-compact`;
} else {
return logsTextColor;
}
}
/**
* Execute a code when a user changes the selected option for console font size.
* @export
*/
onFontSizeChange() { this.logsService.setCompact(); }
/**
* Execute a code when a user changes the selected option for console color.
* @export
*/
onTextColorChange() { this.logsService.setInverted(); }
/**
* Find Pod by name.
* Return object or undefined if can not find a object.
* @param {!Array<!backendApi.ReplicationControllerPodWithContainers>} array
* @param {!string} name
* @return {!backendApi.ReplicationControllerPodWithContainers|undefined}
* @private
*/
findPodByName_(array, name) {
for (let i = 0; i < array.length; i++) {
if (array[i].name === name) {
return array[i];
}
}
return undefined;
}
/**
* Find Container by name.
* Return object or undefined if can not find a object.
* @param {!Array<!backendApi.PodContainer>} array
* @param {string} name
* @return {!backendApi.PodContainer}
* @private
*/
initializeContainer_(array, name) {
let container = undefined;
for (let i = 0; i < array.length; i++) {
if (array[i].name === name) {
container = array[i];
break;
}
}
if (!container) {
container = array[0];
}
return container;
}
}
/**
* Definition object for the component that displays replication controller events card.
*
* @type {!angular.Component}
*/
export const logsToolbarComponent = {
templateUrl: 'logs/logstoolbar/logstoolbar.html',
controller: LogsToolbarController,
controllerAs: 'ctrl',
bindings: {
'containers': '<',
'logsService': '<',
},
};
const i18n = {
/** @export {string} @desc Label 'Pod' on the toolbar of the logs page. Ends with colon. */
MSG_LOGS_POD_LABEL: goog.getMsg('Pod:'),
/** @export {string} @desc Label 'Container' on the toolbar of the logs page. Ends with colon. */
MSG_LOGS_CONTAINER_LABEL: goog.getMsg('Container:'),
};
......@@ -21,6 +21,9 @@ describe('Logs controller', () => {
/** @type {string} */
const logsTextColorClassName = 'kd-logs-text-color-invert';
/** @type {string} */
const logsTextSizeClassName = 'kd-logs-element';
/** @type {!LogsController} */
let ctrl;
......@@ -79,9 +82,10 @@ describe('Logs controller', () => {
it('should instantiate the controller properly', () => { expect(ctrl).not.toBeUndefined(); });
it('should return style class for logs content', () => {
it('should return style classes for logs content', () => {
// expect
expect(ctrl.getStyleClass()).toEqual(`${logsTextColorClassName}`);
expect(ctrl.getLogsClass()).toEqual(`${logsTextSizeClassName}`);
});
it('should display zero state log line if server returned no logs', () => {
......
// 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 LogsModule from 'logs/logs_module';
import {StateParams} from 'logs/logs_state';
describe('Logs toolbar controller', () => {
/** @type {string} */
const iconColorClassName = 'kd-logs-color-icon-invert';
/** @type {string} */
const iconSizeClassName = 'kd-logs-size-icon';
/** @type {string} */
const mockNamespace = 'namespace';
/** @type {string} */
const mockReplicationController = 'replicationController';
/** @type {string} */
const mockPodId = 'pod2';
/** @type {string} */
const mockContainer = 'con22';
/** @type {!backendApi.Logs} */
const logs = {
container: mockContainer,
};
/** @type {!StateParams} */
const stateParams =
new StateParams(mockNamespace, mockReplicationController, mockPodId, mockContainer);
/** @type {!backendApi.PodContainers} */
const podContainers = {containers: ['con1']};
/**
* Logs menu controller.
* @type {!LogsToolbarController}
*/
let ctrl;
/** @type {!ui.router.$state} */
let state;
beforeEach(() => {
angular.mock.module(LogsModule.name);
angular.mock.inject(($componentController, $state) => {
state = $state;
ctrl = $componentController(
'kdLogsToolbar', {$stateParams: stateParams, $state: $state},
{containers: podContainers.containers, podLogs: logs});
});
});
it('should instantiate the controller properly', () => { expect(ctrl).not.toBeUndefined(); });
it('should find objects (pod and container) by name passed in state params',
() => { expect(ctrl.container).toEqual('pod2'); });
it('should call transitionTo on container change', () => {
// given
spyOn(state, 'transitionTo');
// when
ctrl.onContainerChange('container');
// then
expect(state.transitionTo).toHaveBeenCalled();
});
it('should return style class for icon', () => {
// then
expect(ctrl.getColorIconClass()).toEqual(`${iconColorClassName}`);
expect(ctrl.getSizeIconClass()).toEqual(`${iconSizeClassName}`);
});
});
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册