AMBARI-22208 Log Search UI: small fixes for top part of Service Logs page. (Istvan Tobias via ababiichuk)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6f598067 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6f598067 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6f598067 Branch: refs/heads/feature-branch-AMBARI-21307 Commit: 6f598067f7f10b0543a3239884d380546fcdec56 Parents: 4a47e79 Author: Istvan Tobias <tobias.ist...@gmail.com> Authored: Wed Oct 11 19:27:37 2017 +0300 Committer: ababiichuk <ababiic...@hortonworks.com> Committed: Wed Oct 11 20:07:35 2017 +0300 ---------------------------------------------------------------------- .../ambari-logsearch-web/src/app/app.module.ts | 2 + .../accordion-panel.component.less | 2 +- .../src/app/components/app.component.less | 2 +- .../collapsible-panel.component.html | 27 +++ .../collapsible-panel.component.less | 42 ++++ .../collapsible-panel.component.spec.ts | 129 ++++++++++++ .../collapsible-panel.component.ts | 89 +++++++++ .../dropdown-button.component.less | 2 +- .../dropdown-list/dropdown-list.component.less | 2 +- .../filters-panel/filters-panel.component.html | 2 +- .../filters-panel/filters-panel.component.less | 6 +- .../log-file-entry.component.less | 2 +- .../logs-container.component.html | 14 +- .../logs-container.component.spec.ts | 5 + .../logs-container/logs-container.component.ts | 10 + .../logs-list/logs-list.component.less | 2 +- .../main-container.component.less | 2 +- .../src/app/components/main.less | 20 ++ .../menu-button/menu-button.component.less | 18 +- .../menu-button/menu-button.component.ts | 5 +- .../src/app/components/mixins.less | 200 +++++++++++++++++++ .../pagination-controls.component.less | 2 +- .../pagination/pagination.component.less | 4 +- .../search-box/search-box.component.less | 2 +- .../time-histogram.component.less | 2 +- .../time-range-picker.component.less | 2 +- .../components/top-menu/top-menu.component.html | 2 +- .../components/top-menu/top-menu.component.less | 2 +- .../src/app/components/variables.less | 123 +----------- .../src/assets/i18n/en.json | 9 +- 30 files changed, 591 insertions(+), 140 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts b/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts index ff791fe..12b95a7 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts +++ b/ambari-logsearch/ambari-logsearch-web/src/app/app.module.ts @@ -65,6 +65,7 @@ import {FilterDropdownComponent} from '@app/components/filter-dropdown/filter-dr import {DropdownListComponent} from '@app/components/dropdown-list/dropdown-list.component'; import {FilterButtonComponent} from '@app/components/filter-button/filter-button.component'; import {AccordionPanelComponent} from '@app/components/accordion-panel/accordion-panel.component'; +import {CollapsiblePanelComponent} from '@app/components/collapsible-panel/collapsible-panel.component'; import {LogsListComponent} from '@app/components/logs-list/logs-list.component'; import {DropdownButtonComponent} from '@app/components/dropdown-button/dropdown-button.component'; import {PaginationComponent} from '@app/components/pagination/pagination.component'; @@ -115,6 +116,7 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR FilterDropdownComponent, FilterButtonComponent, AccordionPanelComponent, + CollapsiblePanelComponent, LogsListComponent, DropdownButtonComponent, PaginationComponent, http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/accordion-panel/accordion-panel.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/accordion-panel/accordion-panel.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/accordion-panel/accordion-panel.component.less index 8366952..3d083be 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/accordion-panel/accordion-panel.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/accordion-panel/accordion-panel.component.less @@ -15,7 +15,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; .panel-body { position: relative; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/app.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/app.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/app.component.less index d1aa7ff..8731582 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/app.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/app.component.less @@ -15,7 +15,7 @@ * limitations under the License. */ -@import 'variables'; +@import 'mixins'; :host { .full-size; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html new file mode 100644 index 0000000..b73fa45 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.html @@ -0,0 +1,27 @@ +<!-- + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You 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 [ngClass]="{'panel': true, 'panel-default': true, 'panel-collapsible': true, 'panel-collapsed': isCollapsed}"> + <div [ngClass]="{'panel-heading': true}" (click)="handleCollapseBtnClick($event)"> + <a [attr.aria-collapsed]="isCollapsed"> + <i [ngClass]="{'fa': true, 'fa-caret-down': !isCollapsed, 'fa-caret-right': isCollapsed}"></i> + {{((isCollapsed ? collapsedTitle : openTitle) || title) | translate}} + </a> + </div> + <div [ngClass]="{'panel-body': true}" [attr.aria-collapsed]="isCollapsed"> + <ng-content></ng-content> + </div> +</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.less new file mode 100644 index 0000000..40e8e8fd --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.less @@ -0,0 +1,42 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 '../mixins'; + +.panel-collapsible { + position: relative; + .panel-heading { + .clickable-item; + background-color: @panel-heading; + border: 0 none; + color: @base-font-color; + font-size: 1.25rem; + a, a:hover, a:visited { + color: @base-font-color; + text-decoration: none; + } + } + .panel-body { + padding: 5px; + } + &.panel-collapsed { + .panel-body { + height: 0; + overflow: hidden; + } + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts new file mode 100644 index 0000000..60b7d63 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.spec.ts @@ -0,0 +1,129 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 {DebugElement} from '@angular/core'; +import {async, ComponentFixture, TestBed} from '@angular/core/testing'; +import {By} from '@angular/platform-browser'; +import {TranslationModules} from '@app/test-config.spec'; +import {HttpClientService} from '@app/services/http-client.service'; + +//import {AppModule} from '@app/app.module'; +import {CollapsiblePanelComponent} from './collapsible-panel.component'; + +describe('CollapsiblePanelComponent', () => { + let component: CollapsiblePanelComponent; + let fixture: ComponentFixture<CollapsiblePanelComponent>; + let de: DebugElement; + let el: HTMLElement; + + beforeEach(async(() => { + TestBed.configureTestingModule({ + declarations: [CollapsiblePanelComponent], + imports: TranslationModules, + providers: [ + HttpClientService + ] + }) + .compileComponents(); + })); + + beforeEach(() => { + fixture = TestBed.createComponent(CollapsiblePanelComponent); + component = fixture.componentInstance; + fixture.detectChanges(); + de = fixture.debugElement.query(By.css('div.panel')); + el = de.nativeElement; + }); + + it('should create component', () => { + expect(component).toBeTruthy(); + }); + + it('should call toggleCollapsed', () => { + let mockEvent: MouseEvent = document.createEvent('MouseEvent'); + mockEvent.initEvent('click', true, true); + spyOn(component,'toggleCollapsed'); + component.handleCollapseBtnClick(mockEvent); + expect(component.toggleCollapsed).toHaveBeenCalled(); + }); + + it('should prevent default action on event after toggle button click',() => { + let mockEvent: MouseEvent = document.createEvent('MouseEvent'); + mockEvent.initEvent('click', true, true); + spyOn(mockEvent,'preventDefault'); + component.handleCollapseBtnClick(mockEvent); + expect(mockEvent.preventDefault).toHaveBeenCalled(); + }); + + it('should negate the isCollapsed property', () => { + let valueBefore = component.isCollapsed; + component.toggleCollapsed(); + fixture.detectChanges(); + expect(component.isCollapsed).toEqual(!valueBefore); + }); + + it('should add `panel-collapsed` css class to the element when the isCollapsed is true', () => { + component.isCollapsed = true; + fixture.detectChanges(); + expect(el.className).toContain('panel-collapsed'); + }); + + it('should not have `panel-collapsed` css class on the element when the isCollapsed is false', () => { + component.isCollapsed = false; + fixture.detectChanges(); + expect(el.className).not.toContain('panel-collapsed'); + }); + + it('should display the openTitle if presented and the isCollapsed property is false', () => { + let title = 'Open title'; + let headingEl = el.querySelector('.panel-heading'); + component.openTitle = title; + component.isCollapsed = false; + fixture.detectChanges(); + expect(headingEl.textContent).toContain(title); + }); + + it('should display the collapsedTitle if it presented and the isCollapsed property is true', () => { + let title = 'Collapsed title'; + let headingEl = el.querySelector('.panel-heading'); + component.collapsedTitle = title; + component.isCollapsed = true; + fixture.detectChanges(); + expect(headingEl.textContent).toContain(title); + }); + + it('should display the title if openTitle is not presented and the isCollapsed property is false', () => { + let title = 'Title'; + let headingEl = el.querySelector('.panel-heading'); + component.openTitle = ''; + component.title = title; + component.isCollapsed = false; + fixture.detectChanges(); + expect(headingEl.textContent).toContain(title); + }); + + it('should display the title if collapsedTitle is not presented and the isCollapsed property is true', () => { + let title = 'Title'; + let headingEl = el.querySelector('.panel-heading'); + component.collapsedTitle = ''; + component.title = title; + component.isCollapsed = true; + fixture.detectChanges(); + expect(headingEl.textContent).toContain(title); + }); + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts new file mode 100644 index 0000000..cbc0dd7 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/collapsible-panel/collapsible-panel.component.ts @@ -0,0 +1,89 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You 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 {Component, Input} from '@angular/core'; + +enum Side { + LEFT = "left", + RIGHT = "right" +} + +/** + * The goal of this component to have a simple BS panel with a collapse link in the panel heading. So that adding + * components/content into the body of the panel we can hide and show the its content. + * @class CollapsiblePanelComponent + */ +@Component({ + selector: 'collapsible-panel', + templateUrl: './collapsible-panel.component.html', + styleUrls: ['./collapsible-panel.component.less'] +}) +export class CollapsiblePanelComponent { + + /** + * This is for the common title of the panel. If the openTitle or the collapsedTitle not set this will be displayed. + * @type {string} + */ + @Input() + title: string = ''; + + /** + * The panel's title for the opened state + * @type {string} + */ + @Input() + openTitle: string = 'common.hide'; + + /** + * The panel's title fo the closed/collapsed state + * @type {string} + */ + @Input() + collapsedTitle: string = 'common.show'; + + /** + * This property indicates the position of the caret. It can be 'left' or 'right' + * @type {Side} + */ + @Input() + caretSide: Side = Side.LEFT; + + /** + * The flag to indicate the collapsed state. + * @type {boolean} + */ + @Input() + isCollapsed: boolean = false; + + /** + * The goal is to handle the click event of the collapse link/button. It will simply call the inside logic to toggle + * the collapsed state. The goal is to separate the functions by responsibility. + * @param {MouseEvent} ev + */ + handleCollapseBtnClick(ev: MouseEvent): void { + this.toggleCollapsed(); + ev.preventDefault(); + } + + /** + * The goal is to simply negate the current collapse state. + */ + toggleCollapsed():void { + this.isCollapsed = !this.isCollapsed; + } + +} http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less index a5da7f5..d767e15 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-button/dropdown-button.component.less @@ -15,7 +15,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; :host { .default-flex; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.less index 6faa192..674b195 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/dropdown-list/dropdown-list.component.less @@ -16,7 +16,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; :host { max-height: @dropdown-max-height; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html index e0db997..22ec8fe 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.html @@ -30,7 +30,7 @@ <span class="fa fa-search"></span> </button--> </div> - <div class="default-flex col-md-4"> + <div class="filter-buttons col-md-4"> <dropdown-button [options]="searchBoxItems" iconClass="fa fa-search-minus" label="filter.excluded" [hideCaret]="true" [showSelectedValue]="false" action="proceedWithExclude"></dropdown-button> <filter-button formControlName="hosts" label="{{filters.hosts.label | translate}}" http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less index aeb6911..962199b 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/filters-panel/filters-panel.component.less @@ -16,7 +16,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; :host { display: block; @@ -66,4 +66,8 @@ /deep/ .stop-icon { color: @exclude-color; } + + .filter-buttons { + .default-flex; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/log-file-entry/log-file-entry.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/log-file-entry/log-file-entry.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/log-file-entry/log-file-entry.component.less index d3523d3..630565b 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/log-file-entry/log-file-entry.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/log-file-entry/log-file-entry.component.less @@ -15,7 +15,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; :host { display: block; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html index 776bb9a..8b63278 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.html @@ -20,9 +20,17 @@ {{'filter.capture.triggeringRefresh' | translate: autoRefreshMessageParams}} </div> </div> -<time-histogram class="col-md-12" [data]="histogramData" [customOptions]="histogramOptions" - svgId="service-logs-histogram" - (selectArea)="setCustomTimeRange($event[0], $event[1])"></time-histogram> +<!-- TODO use plugin for singular/plural --> +<div class="logs-header col-md-12">{{ + (!totalEventsFoundMessageParams.totalCount ? 'logs.noEventFound' : + (totalEventsFoundMessageParams.totalCount === 1 ? 'logs.oneEventFound' : 'logs.totalEventFound')) + | translate: totalEventsFoundMessageParams +}}</div> +<collapsible-panel openTitle="logs.hideGraph" collapsedTitle="logs.showGraph" class="col-md-12"> + <time-histogram class="col-md-12" [data]="histogramData" [customOptions]="histogramOptions" + svgId="service-logs-histogram" + (selectArea)="setCustomTimeRange($event[0], $event[1])"></time-histogram> +</collapsible-panel> <dropdown-button *ngIf="!isServiceLogsFileView" class="pull-right" label="logs.columns" [options]="availableColumns | async" [isRightAlign]="true" [isMultipleChoice]="true" action="updateSelectedColumns" [additionalArgs]="logsTypeMapObject.fieldsModel"></dropdown-button> http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts index f3b28d1..9b3a043 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.spec.ts @@ -104,4 +104,9 @@ describe('LogsContainerComponent', () => { it('should create component', () => { expect(component).toBeTruthy(); }); + + it('totalEventsFoundMessageParams should provide total count number', () => { + expect(Object.keys(component.totalEventsFoundMessageParams)).toContain('totalCount'); + }); + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts index 63fafb6..cdc023d 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-container/logs-container.component.ts @@ -113,6 +113,16 @@ export class LogsContainerComponent implements OnInit { }; } + /** + * The goal is to provide the single source for the parameters of 'xyz events found' message. + * @returns {Object} + */ + get totalEventsFoundMessageParams(): object { + return { + totalCount: this.totalCount + } + } + isServiceLogContextView: boolean = false; get isServiceLogsFileView(): boolean { http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less index 0fded67..67d0615 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/logs-list/logs-list.component.less @@ -15,7 +15,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; .logs-header { // TODO get rid of magic numbers, base on actual design http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/main-container/main-container.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/main-container/main-container.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/main-container/main-container.component.less index f7dcc05..b596a3d 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/main-container/main-container.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/main-container/main-container.component.less @@ -16,7 +16,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; :host { .full-size; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/main.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/main.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/main.less new file mode 100644 index 0000000..2580710 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/main.less @@ -0,0 +1,20 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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"; +@import "mixins"; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less index 6a3a43d..615db24 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.less @@ -15,19 +15,31 @@ * limitations under the License. */ +@import '../variables'; + :host { - display: inline-block; cursor: pointer; - + display: inline-block; + position: relative; a:hover, a:focus { text-decoration: none; } .icon { - padding: 5px; + padding: @icon-padding; } .unstyled-link { color: inherit; } + + .badge { + background: @badge-bg; + font-size: 1rem; + min-width: 1em; + padding: @badge-padding; + position: absolute; + top: 0; + right: -1em; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts index 3bac984..0aa7c7e 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/menu-button/menu-button.component.ts @@ -61,6 +61,9 @@ export class MenuButtonComponent { @Input() additionalLabelComponentSetter?: string; + @Input() + badge: string; + get hasSubItems(): boolean { return Boolean(this.subItems && this.subItems.length); } @@ -90,7 +93,7 @@ export class MenuButtonComponent { event.stopPropagation(); } } - + updateValue(options: ListItem) { // TODO implement value change behaviour } http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less new file mode 100644 index 0000000..2e46213 --- /dev/null +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/mixins.less @@ -0,0 +1,200 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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'; + +// Mixins +.flex-vertical-align { + display: flex; + align-items: center; +} + +.default-flex { + .flex-vertical-align; + justify-content: space-between; +} + +.common-hexagon(@side, @color) { + display: block; + position: absolute; + margin: (@side / 3.464101615) 0; + width: @side; + height: @side / 1.732050808; + background-color: @color; + + &:before, &:after { + display: block; + position: absolute; + width: 0; + border-left: (@side / 2) solid transparent; + border-right: (@side / 2) solid transparent; + content: ''; + } + + &:before { + bottom: 100%; + border-bottom: (@side / 3.464101615) solid @color; + } + + &:after { + top: 100%; + border-top: (@side / 3.464101615) solid @color; + } +} + +.clickable-item { + cursor: pointer; + color: @link-color; + + &:hover { + color: @link-hover-color; + } +} + +.full-size { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; +} + +.dropdown-list-default { + line-height: 1; + border-radius: 2px; + font-size: 14px; + min-width: @dropdown-min-width; + background: #FFF; + color: #666; + border: 1px solid #CFD3D7; + padding: 5px 0; + margin: 2px 0 0; + text-align: left; + list-style: none; + box-shadow: 0 6px 12px rgba(0, 0, 0, .175); +} + +.dropdown-item-default { + display: block; + padding: 3px 20px; + clear: both; + font-weight: 400; + line-height: 1.42857143; + color: #333; + white-space: nowrap; + cursor: pointer; + + &:hover { + color: #262626; + text-decoration: none; + background-color: #F5F5F5; + } +} + +.log-colors { + &.fatal { + color: @fatal-color; + } + + &.error { + color: @error-color; + } + + &.warn { + color: @warning-color; + } + + &.info { + color: @info-color; + } + + &.debug { + color: @debug-color; + } + + &.trace { + color: @trace-color; + } + + &.unknown { + color: @unknown-color; + } +} + +/** + * Caret mixin definition. + * The .caret mixin has two parameters: the width of the caret and the direction of the caret + * This is the Less implementation of the Bootstrap caret mixin: + * https://github.com/twbs/bootstrap/blob/v4-dev/scss/mixins/_caret.scss + */ + +// This small mixin create the css of the down direction of a caret +.caret-direction(@caret-width, @direction, @color) when (@direction = down) { + border-top: @caret-width solid @color; + border-right: @caret-width solid transparent; + border-bottom: 0; + border-left: @caret-width solid transparent; +} +// This small mixin to create the css for the up direction +.caret-direction(@caret-width, @direction, @color) when (@direction = up) { + border-top: 0; + border-right: @caret-width solid transparent; + border-bottom: @caret-width solid @color; + border-left: @caret-width solid transparent; +} +// This small mixin to create the css for the right direction +.caret-direction(@caret-width, @direction, @color) when (@direction = right) { + border-top: @caret-width solid transparent; + border-right: 0; + border-bottom: @caret-width solid transparent; + border-left: @caret-width solid @color; +} +// This small mixin to create the css for the left direction +.caret-direction(@caret-width, @direction, @color) when (@direction = left) { + border-top: @caret-width solid transparent; + border-right: @caret-width solid @color; + border-bottom: @caret-width solid transparent; + border-left: 0; +} +// This is the content for the caret pseaudo element. It has been moved out from the .caret definition because +// the property interpolation does not work so that we can use condition +.caret-style(@caret-width, @direction, @color) { + display: inline-block; + width: 0; + height: 0; + margin-left: @caret-width * .85; + vertical-align: @caret-width * .85; + content: ""; + .caret-direction(@caret-width, @direction, @color); +} +// This is the main caret mixin to create the common and the direction related css +.caret(@caret-width; @direction: down; @color: @base-font-color; @position: before) { + + &::before when (@position = before) { + .caret-style(@caret-width, @direction, @color); + } + &::after when (@position = after) { + .caret-style(@caret-width, @direction, @color); + } + + &:empty::before when (@position = before) { + margin-left: 0; + } + &:empty::after when (@position = after) { + margin-left: 0; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination-controls/pagination-controls.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination-controls/pagination-controls.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination-controls/pagination-controls.component.less index 8238eaf..ab615f1 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination-controls/pagination-controls.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination-controls/pagination-controls.component.less @@ -16,7 +16,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; .pagination-control { .clickable-item; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.less index df8ad2d..f3f12f7 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/pagination/pagination.component.less @@ -16,7 +16,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; :host { display: flex; @@ -25,4 +25,4 @@ .flex-vertical-align; justify-content: flex-end; } -} \ No newline at end of file +} http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less index 6d4378b..f0a5ce0 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/search-box/search-box.component.less @@ -16,7 +16,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; @inactive-input-width: 1px; @label-margin: 2px; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less index 1d29c55..6fe6292 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-histogram/time-histogram.component.less @@ -18,7 +18,7 @@ :host { cursor: crosshair; - + background: #ECECEC; // TODO add style according to actual design /deep/ .axis { .domain { display: none; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.less index 7d45778..24b1efa 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/time-range-picker/time-range-picker.component.less @@ -16,7 +16,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; .btn.dropdown-toggle { text-transform: none; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html index 3af1a69..a7858a5 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.html @@ -17,5 +17,5 @@ <menu-button *ngFor="let item of items" label="{{item.label | translate}}" [action]="item.action" [iconClass]="item.iconClass" [labelClass]="item.labelClass" - [subItems]="item.subItems" [hideCaret]="item.hideCaret"> + [subItems]="item.subItems" [hideCaret]="item.hideCaret" [badge]="item.badge"> </menu-button> http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less index e5e85f4..4fe899a 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/top-menu/top-menu.component.less @@ -15,7 +15,7 @@ * limitations under the License. */ -@import '../variables'; +@import '../mixins'; :host { .default-flex; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less b/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less index 2dc6278..150ac56 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less +++ b/ambari-logsearch/ambari-logsearch-web/src/app/components/variables.less @@ -17,6 +17,7 @@ */ // Variables +@base-font-color: #666; @navbar-background-color: #323544; @h1-vertical-margin: 20px; @button-border-radius: 4px; @@ -51,120 +52,12 @@ @submit-hover-color: #449D44; @exclude-color: #EF6162; -// Mixins -.flex-vertical-align { - display: flex; - align-items: center; -} +// Panels +@panel-heading: rgba(255, 255, 255, 1); -.default-flex { - .flex-vertical-align; - justify-content: space-between; -} +// Badge +@badge-bg: rgba(239, 97, 98, 1); +@badge-padding: 2px 5px; -.common-hexagon(@side, @color) { - display: block; - position: absolute; - margin: (@side / 3.464101615) 0; - width: @side; - height: @side / 1.732050808; - background-color: @color; - - &:before, &:after { - display: block; - position: absolute; - width: 0; - border-left: (@side / 2) solid transparent; - border-right: (@side / 2) solid transparent; - content: ''; - } - - &:before { - bottom: 100%; - border-bottom: (@side / 3.464101615) solid @color; - } - - &:after { - top: 100%; - border-top: (@side / 3.464101615) solid @color; - } -} - -.clickable-item { - cursor: pointer; - color: @link-color; - - &:hover { - color: @link-hover-color; - } -} - -.full-size { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; -} - -.dropdown-list-default { - line-height: 1; - border-radius: 2px; - font-size: 14px; - min-width: @dropdown-min-width; - background: #FFF; - color: #666; - border: 1px solid #CFD3D7; - padding: 5px 0; - margin: 2px 0 0; - text-align: left; - list-style: none; - box-shadow: 0 6px 12px rgba(0, 0, 0, .175); -} - -.dropdown-item-default { - display: block; - padding: 3px 20px; - clear: both; - font-weight: 400; - line-height: 1.42857143; - color: #333; - white-space: nowrap; - cursor: pointer; - - &:hover { - color: #262626; - text-decoration: none; - background-color: #F5F5F5; - } -} - -.log-colors { - &.fatal { - color: @fatal-color; - } - - &.error { - color: @error-color; - } - - &.warn { - color: @warning-color; - } - - &.info { - color: @info-color; - } - - &.debug { - color: @debug-color; - } - - &.trace { - color: @trace-color; - } - - &.unknown { - color: @unknown-color; - } -} +// Icon +@icon-padding: 5px; http://git-wip-us.apache.org/repos/asf/ambari/blob/6f598067/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json ---------------------------------------------------------------------- diff --git a/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json b/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json index 1dee559..99ddbe5 100644 --- a/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json +++ b/ambari-logsearch/ambari-logsearch-web/src/assets/i18n/en.json @@ -1,5 +1,7 @@ { "common.title": "Log Search", + "common.hide": "Hide", + "common.show": "Show", "modal.submit": "OK", "modal.cancel": "Cancel", @@ -146,5 +148,10 @@ "logs.copy": "Copy", "logs.open": "Open Log", "logs.context": "Context", - "logs.loadMore": "Load more" + "logs.loadMore": "Load more", + "logs.oneEventFound": "1 event found", + "logs.totalEventFound": "{{totalCount}} events found", + "logs.noEventFound": "No event found", + "logs.hideGraph": "Hide Graph", + "logs.showGraph": "Show Graph" }