You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by ab...@apache.org on 2017/07/10 18:02:40 UTC
ambari git commit: AMBARI-21438 Log Search UI: implement sorting of
logs list. (ababiichuk)
Repository: ambari
Updated Branches:
refs/heads/branch-feature-logsearch-ui e5ac65e04 -> 2d5b75618
AMBARI-21438 Log Search UI: implement sorting of logs list. (ababiichuk)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2d5b7561
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2d5b7561
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2d5b7561
Branch: refs/heads/branch-feature-logsearch-ui
Commit: 2d5b75618c36a29792a312ba7c3ccdd01a454220
Parents: e5ac65e
Author: ababiichuk <ab...@hortonworks.com>
Authored: Mon Jul 10 20:58:26 2017 +0300
Committer: ababiichuk <ab...@hortonworks.com>
Committed: Mon Jul 10 20:58:26 2017 +0300
----------------------------------------------------------------------
.../src/app/app.module.ts | 6 +-
.../dropdown-button.component.html | 23 ++++
.../dropdown-button.component.less | 30 +++++
.../dropdown-button.component.spec.ts | 79 +++++++++++
.../dropdown-button.component.ts | 75 +++++++++++
.../dropdown-list.component.spec.ts | 35 ++---
.../dropdown-list/dropdown-list.component.ts | 9 +-
.../filter-button.component.spec.ts | 4 +-
.../filter-button/filter-button.component.ts | 18 +--
.../filter-dropdown.component.html | 23 ----
.../filter-dropdown.component.less | 9 --
.../filter-dropdown.component.spec.ts | 2 +
.../filter-dropdown.component.ts | 48 ++++---
.../filter-text-field.component.html | 3 +-
.../filter-text-field.component.spec.ts | 2 +
.../filter-text-field.component.ts | 33 ++---
.../filters-panel/filters-panel.component.html | 25 ++--
.../filters-panel/filters-panel.component.less | 2 +-
.../filters-panel.component.spec.ts | 4 +-
.../filters-panel/filters-panel.component.ts | 16 +--
.../logs-list/logs-list.component.html | 10 ++
.../logs-list/logs-list.component.less | 14 ++
.../logs-list/logs-list.component.spec.ts | 8 +-
.../components/logs-list/logs-list.component.ts | 18 ++-
.../menu-button/menu-button.component.html | 4 +-
.../menu-button/menu-button.component.ts | 13 +-
.../src/app/components/variables.less | 1 +
.../src/app/services/filtering.service.spec.ts | 4 +-
.../src/app/services/filtering.service.ts | 134 ++++++++++++++-----
.../src/app/services/mock-api-data.service.ts | 22 ++-
.../src/app/services/utils.service.spec.ts | 33 +++++
.../src/app/services/utils.service.ts | 40 ++++++
.../src/assets/i18n/en.json | 13 +-
33 files changed, 562 insertions(+), 198 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts
index 72b5ad1..580fffa 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/app.module.ts
@@ -32,6 +32,7 @@ import {mockApiDataService} from '@app/services/mock-api-data.service'
import {HttpClientService} from '@app/services/http-client.service';
import {ComponentActionsService} from '@app/services/component-actions.service';
import {FilteringService} from '@app/services/filtering.service';
+import {UtilsService} from '@app/services/utils.service';
import {AppSettingsService} from '@app/services/storage/app-settings.service';
import {AppStateService} from '@app/services/storage/app-state.service';
@@ -58,6 +59,7 @@ import {FilterTextFieldComponent} from '@app/components/filter-text-field/filter
import {FilterButtonComponent} from '@app/components/filter-button/filter-button.component';
import {AccordionPanelComponent} from '@app/components/accordion-panel/accordion-panel.component';
import {LogsListComponent} from '@app/components/logs-list/logs-list.component';
+import {DropdownButtonComponent} from '@app/components/dropdown-button/dropdown-button.component';
export function HttpLoaderFactory(http: Http) {
// adding 'static' parameter to step over mock data request
@@ -92,7 +94,8 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR
FilterTextFieldComponent,
FilterButtonComponent,
AccordionPanelComponent,
- LogsListComponent
+ LogsListComponent,
+ DropdownButtonComponent
],
imports: [
BrowserModule,
@@ -115,6 +118,7 @@ export function getXHRBackend(injector: Injector, browser: BrowserXhr, xsrf: XSR
HttpClientService,
ComponentActionsService,
FilteringService,
+ UtilsService,
AppSettingsService,
AppStateService,
AuditLogsService,
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html
new file mode 100644
index 0000000..8eb92f0
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.html
@@ -0,0 +1,23 @@
+<!--
+ 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 class="filter-label" *ngIf="label">{{label | translate}}</div>
+<button class="btn btn-link dropdown-toggle" data-toggle="dropdown">
+ {{selectedLabel | translate}} <span class="caret"></span>
+</button>
+<ul data-component="dropdown-list" [ngClass]="{'dropdown-menu': true, 'dropdown-menu-right': isRightAlign}" [items]="options"
+ (selectedItemChange)="writeValue($event)"></ul>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.less
new file mode 100644
index 0000000..a60246c
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.less
@@ -0,0 +1,30 @@
+/**
+ * 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';
+
+:host {
+ position: relative;
+
+ .filter-label {
+ padding: @input-group-addon-padding;
+ }
+
+ .btn {
+ text-transform: none;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.spec.ts
new file mode 100644
index 0000000..8efe320
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.spec.ts
@@ -0,0 +1,79 @@
+/**
+ * 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 {NO_ERRORS_SCHEMA} from '@angular/core';
+import {async, ComponentFixture, TestBed} from '@angular/core/testing';
+import {Http} from '@angular/http';
+import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
+import {TranslateHttpLoader} from '@ngx-translate/http-loader';
+import {StoreModule} from '@ngrx/store';
+import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
+import {ClustersService, clusters} from '@app/services/storage/clusters.service';
+import {ComponentsService, components} from '@app/services/storage/components.service';
+import {FilteringService} from '@app/services/filtering.service';
+import {UtilsService} from '@app/services/utils.service';
+import {ComponentActionsService} from '@app/services/component-actions.service';
+
+import {DropdownButtonComponent} from './dropdown-button.component';
+
+export function HttpLoaderFactory(http: Http) {
+ return new TranslateHttpLoader(http, 'assets/i18n/', '.json');
+}
+
+describe('DropdownButtonComponent', () => {
+ let component: DropdownButtonComponent;
+ let fixture: ComponentFixture<DropdownButtonComponent>;
+
+ beforeEach(async(() => {
+ TestBed.configureTestingModule({
+ declarations: [DropdownButtonComponent],
+ imports: [
+ StoreModule.provideStore({
+ appSettings,
+ clusters,
+ components
+ }),
+ TranslateModule.forRoot({
+ provide: TranslateLoader,
+ useFactory: HttpLoaderFactory,
+ deps: [Http]
+ })
+ ],
+ providers: [
+ AppSettingsService,
+ ClustersService,
+ ComponentsService,
+ FilteringService,
+ UtilsService,
+ ComponentActionsService
+ ],
+ schemas: [NO_ERRORS_SCHEMA]
+ })
+ .compileComponents();
+ }));
+
+ beforeEach(() => {
+ fixture = TestBed.createComponent(DropdownButtonComponent);
+ component = fixture.componentInstance;
+ fixture.detectChanges();
+ });
+
+ it('should create component', () => {
+ expect(component).toBeTruthy();
+ });
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
new file mode 100644
index 0000000..821f137
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-button/dropdown-button.component.ts
@@ -0,0 +1,75 @@
+/**
+ * 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, OnInit, Input} from '@angular/core';
+import {FilteringService} from '@app/services/filtering.service';
+import {ComponentActionsService} from '@app/services/component-actions.service';
+import {UtilsService} from '@app/services/utils.service';
+
+@Component({
+ selector: 'dropdown-button',
+ templateUrl: './dropdown-button.component.html',
+ styleUrls: ['./dropdown-button.component.less']
+})
+export class DropdownButtonComponent implements OnInit {
+
+ constructor(protected filtering: FilteringService, protected actions: ComponentActionsService, protected utils: UtilsService) {
+ }
+
+ ngOnInit() {
+ this.selectedLabel = this.defaultLabel;
+ }
+
+ @Input()
+ label?: string;
+
+ @Input()
+ options?: any[];
+
+ @Input()
+ defaultValue?: string;
+
+ @Input()
+ defaultLabel?: string;
+
+ @Input()
+ action?: string;
+
+ @Input()
+ isRightAlign?: boolean = false;
+
+ private selectedValue?: any;
+
+ selectedLabel: string;
+
+ get value(): any {
+ return this.selectedValue == null ? this.defaultValue : this.selectedValue;
+ }
+
+ writeValue(options: any) {
+ const value = options && options.value;
+ if (this.utils.valueHasChanged(this.value, value)) {
+ this.selectedValue = value;
+ this.selectedLabel = options.label;
+ if (this.action) {
+ this.actions[this.action](value);
+ }
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
index 445ee97..e16d93a 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.spec.ts
@@ -55,37 +55,22 @@ describe('DropdownListComponent', () => {
describe('#changeSelectedItem()', () => {
+ const options = {
+ label: 'l',
+ value: 'v'
+ };
+
beforeEach(() => {
spyOn(component.selectedItemChange, 'emit').and.callFake(() => {});
+ component.changeSelectedItem(options);
});
- describe('not a filter list', () => {
- it('event should not be emitted', () => {
- component.isFilter = false;
- component.changeSelectedItem({});
- expect(component.selectedItemChange.emit).not.toHaveBeenCalled();
- });
+ it('event should be emitted', () => {
+ expect(component.selectedItemChange.emit).toHaveBeenCalled();
});
- describe('filter list', () => {
- const options = {
- label: 'l',
- value: 'v'
- };
-
- beforeEach(() => {
- component.isFilter = true;
- component.changeSelectedItem(options);
- });
-
- it('event should be emitted', () => {
- expect(component.selectedItemChange.emit).toHaveBeenCalled();
- });
-
- it('event emitter should be called with correct arguments', () => {
- expect(component.selectedItemChange.emit).toHaveBeenCalledWith(options);
- });
-
+ it('event emitter should be called with correct arguments', () => {
+ expect(component.selectedItemChange.emit).toHaveBeenCalledWith(options);
});
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
index 6426f6a..3e9a445 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/dropdown-list/dropdown-list.component.ts
@@ -19,7 +19,7 @@
import {Component, Input, Output, EventEmitter} from '@angular/core';
@Component({
- selector: 'ul.dropdown-menu',
+ selector: 'ul[data-component="dropdown-list"]',
templateUrl: './dropdown-list.component.html',
styleUrls: ['./dropdown-list.component.less']
})
@@ -31,16 +31,11 @@ export class DropdownListComponent {
@Input()
defaultAction: Function;
- @Input()
- isFilter: boolean;
-
@Output()
selectedItemChange: EventEmitter<any> = new EventEmitter();
changeSelectedItem(options: any): void {
- if (this.isFilter) {
- this.selectedItemChange.emit(options);
- }
+ this.selectedItemChange.emit(options);
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
index dda81e6..370b46e 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.spec.ts
@@ -28,6 +28,7 @@ import {ClustersService, clusters} from '@app/services/storage/clusters.service'
import {ComponentsService, components} from '@app/services/storage/components.service';
import {ComponentActionsService} from '@app/services/component-actions.service';
import {FilteringService} from '@app/services/filtering.service';
+import {UtilsService} from '@app/services/utils.service';
import {FilterButtonComponent} from './filter-button.component';
@@ -58,7 +59,8 @@ describe('FilterButtonComponent', () => {
ClustersService,
ComponentsService,
ComponentActionsService,
- FilteringService
+ FilteringService,
+ UtilsService
],
schemas: [NO_ERRORS_SCHEMA]
})
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
index b529686..27456e6 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-button/filter-button.component.ts
@@ -20,6 +20,7 @@ import {Component, Input, forwardRef} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from '@angular/forms';
import {ComponentActionsService} from '@app/services/component-actions.service';
import {FilteringService} from '@app/services/filtering.service';
+import {UtilsService} from '@app/services/utils.service';
import {MenuButtonComponent} from '@app/components/menu-button/menu-button.component';
@Component({
@@ -36,29 +37,18 @@ import {MenuButtonComponent} from '@app/components/menu-button/menu-button.compo
})
export class FilterButtonComponent extends MenuButtonComponent implements ControlValueAccessor {
- constructor(protected actions: ComponentActionsService, private filtering: FilteringService) {
+ constructor(protected actions: ComponentActionsService, private filtering: FilteringService, private utils: UtilsService) {
super(actions);
}
- ngAfterViewInit() {
- const callback = this.customOnChange ?
- (value => this.actions[this.customOnChange](value)) : (() => this.filtering.filteringSubject.next(null));
- this.form.controls[this.filterName].valueChanges.subscribe(callback);
- }
-
@Input()
filterName: string;
@Input()
- customOnChange: string;
-
- @Input()
form: FormGroup;
private onChange: (fn: any) => void;
- readonly isFilter = true;
-
get filterInstance(): any {
return this.filtering.filters[this.filterName];
}
@@ -68,7 +58,7 @@ export class FilterButtonComponent extends MenuButtonComponent implements Contro
}
set value(newValue: any) {
- if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
+ if (this.utils.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
this.filterInstance.selectedValue = newValue;
this.onChange(newValue);
}
@@ -76,7 +66,7 @@ export class FilterButtonComponent extends MenuButtonComponent implements Contro
writeValue(options: any) {
const value = options && options.value;
- if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, value)) {
+ if (this.utils.valueHasChanged(this.filterInstance.selectedValue, value)) {
this.filterInstance.selectedValue = value;
this.filterInstance.selectedLabel = options.label;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html
deleted file mode 100644
index bb7a206..0000000
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.html
+++ /dev/null
@@ -1,23 +0,0 @@
-<!--
- 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 class="filter-label" *ngIf="filterInstance.label">{{filterInstance.label | translate}}</div>
-<button class="btn btn-link dropdown-toggle" data-toggle="dropdown">
- {{filterInstance.selectedLabel | translate}} <span class="caret"></span>
-</button>
-<ul class="dropdown-menu" [items]="filterInstance.options" [isFilter]="true"
- (selectedItemChange)="writeValue($event)"></ul>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.less
index ec8e84b..e5e85f4 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.less
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.less
@@ -18,14 +18,5 @@
@import '../variables';
:host {
- position: relative;
.default-flex;
-
- .filter-label {
- padding: @input-group-addon-padding;
- }
-
- .btn {
- text-transform: none;
- }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
index f6d1294..e05ef48 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.spec.ts
@@ -24,6 +24,7 @@ import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {StoreModule} from '@ngrx/store';
import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
import {FilteringService} from '@app/services/filtering.service';
+import {UtilsService} from '@app/services/utils.service';
import {ComponentActionsService} from '@app/services/component-actions.service';
import {FilterDropdownComponent} from './filter-dropdown.component';
@@ -71,6 +72,7 @@ describe('FilterDropdownComponent', () => {
provide: FilteringService,
useValue: filtering
},
+ UtilsService,
ComponentActionsService
],
schemas: [NO_ERRORS_SCHEMA]
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts
index 1cf7d41..9ebd821 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-dropdown/filter-dropdown.component.ts
@@ -15,15 +15,17 @@
* limitations under the License.
*/
-import {Component, AfterViewInit, Input, forwardRef} from '@angular/core';
+import {Component, Input, forwardRef} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from '@angular/forms';
import {FilteringService} from '@app/services/filtering.service';
import {ComponentActionsService} from '@app/services/component-actions.service';
+import {UtilsService} from '@app/services/utils.service';
+import {DropdownButtonComponent} from '@app/components/dropdown-button/dropdown-button.component';
@Component({
selector: 'filter-dropdown',
- templateUrl: './filter-dropdown.component.html',
- styleUrls: ['./filter-dropdown.component.less'],
+ templateUrl: '../dropdown-button/dropdown-button.component.html',
+ styleUrls: ['../dropdown-button/dropdown-button.component.less', './filter-dropdown.component.less'],
providers: [
{
provide: NG_VALUE_ACCESSOR,
@@ -32,24 +34,16 @@ import {ComponentActionsService} from '@app/services/component-actions.service';
}
]
})
-export class FilterDropdownComponent implements AfterViewInit, ControlValueAccessor {
+export class FilterDropdownComponent extends DropdownButtonComponent implements ControlValueAccessor {
- constructor(private filtering: FilteringService, private actions: ComponentActionsService) {
+ constructor(protected filtering: FilteringService, protected actions: ComponentActionsService, protected utils: UtilsService) {
+ super(filtering, actions, utils);
}
- ngAfterViewInit() {
- const callback = this.customOnChange ?
- (value => this.actions[this.customOnChange](value)) : (() => this.filtering.filteringSubject.next(null));
- this.form.controls[this.filterName].valueChanges.subscribe(callback);
+ ngOnInit() {
}
@Input()
- options: any[];
-
- @Input()
- customOnChange: string;
-
- @Input()
form: FormGroup;
@Input()
@@ -61,20 +55,36 @@ export class FilterDropdownComponent implements AfterViewInit, ControlValueAcces
return this.filtering.filters[this.filterName];
}
+ get label(): string {
+ return this.filterInstance.label;
+ }
+
+ get defaultValue(): any {
+ return this.filterInstance.defaultValue;
+ }
+
+ get defaultLabel(): any {
+ return this.filterInstance.defaultLabel;
+ }
+
get value(): any {
- return this.filterInstance.selectedValue;
+ return this.filterInstance.selectedValue == null ? this.defaultValue : this.filterInstance.selectedValue;
}
set value(newValue: any) {
- if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
+ if (this.utils.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
this.filterInstance.selectedValue = newValue;
this.onChange(newValue);
}
}
- writeValue(options: any) {
+ get selectedLabel(): string {
+ return this.filterInstance.selectedLabel == null ? this.defaultLabel : this.filterInstance.selectedLabel;
+ }
+
+ writeValue(options: any): void {
const value = options && options.value;
- if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, value)) {
+ if (this.utils.valueHasChanged(this.filterInstance.selectedValue, value)) {
this.filterInstance.selectedValue = value;
this.filterInstance.selectedLabel = options.label;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html
index 8fb7659..d135ba5 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.html
@@ -17,6 +17,5 @@
<div class="input-group">
<span class="input-group-addon">{{filterInstance.label | translate}}</span>
- <input type="text" class="form-control" [(ngModel)]="filterInstance.selectedValue"
- (ngModelChange)="writeValue($event)">
+ <input type="text" class="form-control" [(ngModel)]="instantValue" (ngModelChange)="updateValue($event)">
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts
index 9123969..a30e12a 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.spec.ts
@@ -24,6 +24,7 @@ import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {StoreModule} from '@ngrx/store';
import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
import {FilteringService} from '@app/services/filtering.service';
+import {UtilsService} from '@app/services/utils.service';
import {ComponentActionsService} from '@app/services/component-actions.service';
import {FilterTextFieldComponent} from './filter-text-field.component';
@@ -61,6 +62,7 @@ describe('FilterTextFieldComponent', () => {
provide: FilteringService,
useValue: filtering
},
+ UtilsService,
ComponentActionsService
],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts
index b05000b..fe6ea34 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filter-text-field/filter-text-field.component.ts
@@ -15,11 +15,12 @@
* limitations under the License.
*/
-import {Component, AfterViewInit, Input, forwardRef} from '@angular/core';
+import {Component, Input, forwardRef} from '@angular/core';
import {ControlValueAccessor, NG_VALUE_ACCESSOR, FormGroup} from '@angular/forms';
+import {Subject} from 'rxjs/Subject';
import 'rxjs/add/operator/debounceTime';
import {FilteringService} from '@app/services/filtering.service';
-import {ComponentActionsService} from '@app/services/component-actions.service';
+import {UtilsService} from '@app/services/utils.service';
@Component({
selector: 'filter-text-field',
@@ -33,30 +34,28 @@ import {ComponentActionsService} from '@app/services/component-actions.service';
}
]
})
-export class FilterTextFieldComponent implements AfterViewInit, ControlValueAccessor {
+export class FilterTextFieldComponent implements ControlValueAccessor {
- constructor(private filtering: FilteringService, private actions: ComponentActionsService) {
- }
-
- ngAfterViewInit() {
- const callback = this.customOnChange ?
- (value => this.actions[this.customOnChange](value)) : (() => this.filtering.filteringSubject.next(null));
- this.form.controls[this.filterName].valueChanges.debounceTime(this.debounceInterval).subscribe(callback);
+ constructor(private filtering: FilteringService, private utils: UtilsService) {
+ this.valueSubject.debounceTime(this.debounceInterval).subscribe(value => this.writeValue({
+ value
+ }));
}
@Input()
filterName: string;
@Input()
- customOnChange: string;
-
- @Input()
form: FormGroup;
private onChange: (fn: any) => void;
private readonly debounceInterval = 1500;
+ instantValue: string;
+
+ private valueSubject = new Subject<string>();
+
get filterInstance(): any {
return this.filtering.filters[this.filterName];
}
@@ -66,7 +65,7 @@ export class FilterTextFieldComponent implements AfterViewInit, ControlValueAcce
}
set value(newValue: any) {
- if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
+ if (this.utils.valueHasChanged(this.filterInstance.selectedValue, newValue)) {
this.filterInstance.selectedValue = newValue;
this.onChange(newValue);
}
@@ -74,7 +73,7 @@ export class FilterTextFieldComponent implements AfterViewInit, ControlValueAcce
writeValue(options: any) {
const value = options && options.value;
- if (this.filtering.valueHasChanged(this.filterInstance.selectedValue, value)) {
+ if (this.utils.valueHasChanged(this.filterInstance.selectedValue, value)) {
this.filterInstance.selectedValue = value;
}
}
@@ -86,4 +85,8 @@ export class FilterTextFieldComponent implements AfterViewInit, ControlValueAcce
registerOnTouched() {
}
+ updateValue(value: string): void {
+ this.valueSubject.next(value);
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html
index 450ce5a..6547d88 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.html
@@ -17,15 +17,14 @@
<form [formGroup]="filtersForm">
<div class="form-inline filter-input-container col-md-8">
- <filter-dropdown [(ngModel)]="filters.clusters.selectedValue" [filterName]="'clusters'"
- formControlName="clusters" [form]="filtersForm"></filter-dropdown>
- <filter-text-field [(ngModel)]="filters.text.selectedValue" [filterName]="'text'" formControlName="text"
+ <filter-dropdown [(ngModel)]="filters.clusters.selectedValue" filterName="clusters" [form]="filtersForm"
+ formControlName="clusters" [options]="filters.clusters.options"></filter-dropdown>
+ <filter-text-field [(ngModel)]="filters.text.selectedValue" filterName="text" formControlName="text"
[form]="filtersForm"></filter-text-field>
- <filter-dropdown [(ngModel)]="filters.timeRange.selectedValue" [filterName]="'timeRange'"
- formControlName="timeRange" [form]="filtersForm"></filter-dropdown>
- <filter-dropdown [(ngModel)]="filters.timeZone.selectedValue" [filterName]="'timeZone'"
- formControlName="timeZone" [form]="filtersForm"
- [customOnChange]="'setTimeZone'"></filter-dropdown>
+ <filter-dropdown [(ngModel)]="filters.timeRange.selectedValue" filterName="timeRange" [form]="filtersForm"
+ formControlName="timeRange" [options]="filters.timeRange.options"></filter-dropdown>
+ <dropdown-button [options]="timeZoneSelection.options" [defaultValue]="timeZoneSelection.defaultValue"
+ [defaultLabel]="timeZoneSelection.defaultLabel" action="setTimeZone"></dropdown-button>
<!--button class="btn btn-success" type="button">
<span class="fa fa-search"></span>
</button-->
@@ -34,14 +33,12 @@
<a href="#">
<span class="fa fa-search-minus"></span> {{'filter.excluded' | translate}}
</a>
- <filter-button [(ngModel)]="filters.components.selectedValue" formControlName="components"
+ <filter-button [(ngModel)]="filters.components.selectedValue" [form]="filtersForm" formControlName="components"
[label]="filters.components.label" [iconClass]="filters.components.iconClass"
- [subItems]="filters.components.options" [filterName]="'components'"
- [form]="filtersForm"></filter-button>
- <filter-button [(ngModel)]="filters.levels.selectedValue" formControlName="levels"
+ [subItems]="filters.components.options" filterName="components"></filter-button>
+ <filter-button [(ngModel)]="filters.levels.selectedValue" [form]="filtersForm" formControlName="levels"
[label]="filters.levels.label" [iconClass]="filters.levels.iconClass"
- [subItems]="filters.levels.options" [filterName]="'levels'"
- [form]="filtersForm"></filter-button>
+ [subItems]="filters.levels.options" filterName="levels"></filter-button>
<menu-button label="filter.capture" iconClass="fa fa-caret-right"></menu-button>
</div>
</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less
index 46a157c..aebd385 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.less
@@ -27,7 +27,7 @@
border-bottom-left-radius: 0;
}
- filter-dropdown {
+ filter-dropdown, dropdown-button {
border: @input-border;
&:not(:last-child) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
index 1917f7f..c0234bb 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.spec.ts
@@ -27,6 +27,7 @@ import {ClustersService, clusters} from '@app/services/storage/clusters.service'
import {ComponentsService, components} from '@app/services/storage/components.service';
import {FilteringService} from '@app/services/filtering.service';
import {HttpClientService} from '@app/services/http-client.service';
+import {UtilsService} from '@app/services/utils.service';
import {FiltersPanelComponent} from './filters-panel.component';
@@ -69,7 +70,8 @@ describe('FiltersPanelComponent', () => {
{
provide: HttpClientService,
useValue: httpClient
- }
+ },
+ UtilsService
],
schemas: [NO_ERRORS_SCHEMA]
})
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts
index f42a2bb..9855bdd 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/filters-panel/filters-panel.component.ts
@@ -17,7 +17,6 @@
*/
import {Component} from '@angular/core';
-import {FormControl, FormGroup} from '@angular/forms';
import {FilteringService} from '@app/services/filtering.service';
import {HttpClientService} from '@app/services/http-client.service';
import {ClustersService} from '@app/services/storage/clusters.service';
@@ -35,16 +34,13 @@ export class FiltersPanelComponent {
this.loadComponents();
}
- get filters() {
+ get filters(): any {
return this.filtering.filters;
}
- private filtersFormItems = Object.keys(this.filters).reduce((currentObject, key) => {
- const item = {
- [key]: new FormControl()
- };
- return Object.assign(currentObject, item);
- }, {});
+ get timeZoneSelection(): any {
+ return this.filtering.timeZoneSelection;
+ }
private loadClusters(): void {
this.httpClient.get('clusters').subscribe(response => {
@@ -66,6 +62,8 @@ export class FiltersPanelComponent {
});
}
- filtersForm = new FormGroup(this.filtersFormItems);
+ get filtersForm() {
+ return this.filtering.filtersForm;
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
index 09b2e1e..5977ea2 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.html
@@ -15,6 +15,16 @@
limitations under the License.
-->
+<form *ngIf="(logs | async).length" [formGroup]="filtersForm">
+ <filter-dropdown [(ngModel)]="filters.sorting.selectedValue" filterName="sorting" [form]="filtersForm"
+ formControlName="sorting" [options]="filters.sorting.options" isRightAlign="true"></filter-dropdown>
+</form>
+<div class="col-md-12 text-center" *ngIf="(logs | async).length">
+ <div class="logs-header">
+ <div class="col-md-1">{{'logs.status' | translate}}</div>
+ <div class="col-md-11">{{'logs.details' | translate}}</div>
+ </div>
+</div>
<accordion-panel *ngFor="let log of logs | async; let i = index" [toggleId]="'details-' + i" class="col-md-12">
<ng-template>
<div [ngClass]="'hexagon ' + log.className"></div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less
index 6ed0463..8ebe870 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.less
@@ -23,6 +23,19 @@
padding-top: @block-margin-top;
background-color: @main-background-color; // TODO implement actual color
+ .logs-header {
+ // TODO get rid of magic numbers, base on actual design
+ margin: 10px 0;
+ padding: 5px 0;
+ background-color: @list-header-background-color; // TODO implement actual color
+ overflow: hidden;
+ text-transform: uppercase;
+ }
+
+ filter-dropdown {
+ justify-content: flex-end;
+ }
+
.hexagon {
// TODO get rid of magic numbers, base on actual design
left: -7.5px;
@@ -116,6 +129,7 @@
&.collapsing + .log-content, &.collapse.in + .log-content {
min-height: 6em;
max-height: none;
+ overflow-x: auto;
}
.action-icon {
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
index ffcfb83..2c4f372 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.spec.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-import {CUSTOM_ELEMENTS_SCHEMA} from '@angular/core';
+import {NO_ERRORS_SCHEMA} from '@angular/core';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {StoreModule} from '@ngrx/store';
import {MomentModule} from 'angular2-moment';
@@ -27,6 +27,7 @@ import {ClustersService, clusters} from '@app/services/storage/clusters.service'
import {ComponentsService, components} from '@app/services/storage/components.service';
import {HttpClientService} from '@app/services/http-client.service';
import {FilteringService} from '@app/services/filtering.service';
+import {UtilsService} from '@app/services/utils.service';
import {LogsListComponent} from './logs-list.component';
@@ -66,9 +67,10 @@ describe('LogsListComponent', () => {
AppSettingsService,
ClustersService,
ComponentsService,
- FilteringService
+ FilteringService,
+ UtilsService
],
- schemas: [CUSTOM_ELEMENTS_SCHEMA]
+ schemas: [NO_ERRORS_SCHEMA]
})
.compileComponents();
}));
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts
index bf80445..a070814 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/logs-list/logs-list.component.ts
@@ -29,11 +29,13 @@ import {FilteringService} from '@app/services/filtering.service';
export class LogsListComponent implements OnInit {
constructor(private httpClient: HttpClientService, private serviceLogsStorage: ServiceLogsService, private filtering: FilteringService) {
- this.filtering.filteringSubject.subscribe(this.loadLogs.bind(this));
}
ngOnInit() {
this.loadLogs();
+ this.filtersForm.valueChanges.subscribe(() => {
+ this.loadLogs();
+ });
}
@Input()
@@ -46,7 +48,8 @@ export class LogsListComponent implements OnInit {
text: ['iMessage'],
timeRange: ['end_time', 'start_time'],
components: ['component_name'],
- levels: ['level']
+ levels: ['level'],
+ sorting: ['sortType', 'sortBy']
};
logs = this.serviceLogsStorage.getAll().map(logs => logs.map(log => {
@@ -63,6 +66,14 @@ export class LogsListComponent implements OnInit {
return this.filtering.timeZone;
}
+ get filters() {
+ return this.filtering.filters;
+ }
+
+ get filtersForm() {
+ return this.filtering.filtersForm;
+ }
+
private loadLogs(): void {
this.httpClient.get(this.logsArrayId, this.getParams()).subscribe(response => {
const jsonResponse = response.json(),
@@ -78,8 +89,7 @@ export class LogsListComponent implements OnInit {
private getParams(): any {
let params = {};
Object.keys(this.usedFilters).forEach(key => {
- const inputFilter = this.filtering.filters[key],
- inputValue = inputFilter.selectedValue,
+ const inputValue = this.filtersForm.getRawValue()[key],
paramNames = this.usedFilters[key];
paramNames.forEach(paramName => {
let value;
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
index 5111197..031dec1 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.html
@@ -22,6 +22,6 @@
<br>
<a *ngIf="label" (mousedown)="onMouseDown($event)" [ngClass]="labelClass" (mouseup)="onMouseUp($event)"
(click)="$event.stopPropagation()">{{label | translate}}</a>
- <ul class="dropdown-menu" *ngIf="hasSubItems" [items]="subItems" [isFilter]="isFilter"
- (selectedItemChange)="isFilter && writeValue($event)"></ul>
+ <ul data-component="dropdown-list" class="dropdown-menu" *ngIf="hasSubItems" [items]="subItems"
+ (selectedItemChange)="writeValue($event)"></ul>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
index 0c1f840..e245fb3 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/menu-button/menu-button.component.ts
@@ -16,7 +16,7 @@
* limitations under the License.
*/
-import {Component, AfterViewInit, Input, ViewChild, ElementRef} from '@angular/core';
+import {Component, Input, ViewChild, ElementRef} from '@angular/core';
import {ComponentActionsService} from '@app/services/component-actions.service';
import * as $ from 'jquery';
@@ -25,14 +25,11 @@ import * as $ from 'jquery';
templateUrl: './menu-button.component.html',
styleUrls: ['./menu-button.component.less']
})
-export class MenuButtonComponent implements AfterViewInit {
+export class MenuButtonComponent {
constructor(protected actions: ComponentActionsService) {
}
- ngAfterViewInit() {
- }
-
@ViewChild('dropdown')
dropdown: ElementRef;
@@ -42,8 +39,6 @@ export class MenuButtonComponent implements AfterViewInit {
@Input()
action: string;
- isFilter: boolean = false;
-
@Input()
iconClass: string;
@@ -85,5 +80,9 @@ export class MenuButtonComponent implements AfterViewInit {
event.stopPropagation();
}
}
+
+ writeValue(options: any) {
+ // TODO implement value change behaviour
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less
index 9a8ea09..c5f034c 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/components/variables.less
@@ -29,6 +29,7 @@
@grey-color: #666;
@default-line-height: 1.42857143;
@main-background-color: #ECECEC;
+@list-header-background-color: #F2F2F2;
@fatal-color: #830A0A;
@error-color: #E81D1D;
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
index 0ad3795..4be15b4 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.spec.ts
@@ -21,6 +21,7 @@ import {StoreModule} from '@ngrx/store';
import {AppSettingsService, appSettings} from '@app/services/storage/app-settings.service';
import {ClustersService, clusters} from '@app/services/storage/clusters.service';
import {ComponentsService, components} from '@app/services/storage/components.service';
+import {UtilsService} from '@app/services/utils.service';
import {FilteringService} from './filtering.service';
@@ -38,7 +39,8 @@ describe('FilteringService', () => {
FilteringService,
AppSettingsService,
ClustersService,
- ComponentsService
+ ComponentsService,
+ UtilsService
]
});
});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
index 36bb756..e31202b 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/filtering.service.ts
@@ -17,16 +17,17 @@
*/
import {Injectable} from '@angular/core';
-import {Subject} from 'rxjs/Subject';
+import {FormControl, FormGroup} from '@angular/forms';
import * as moment from 'moment-timezone';
import {AppSettingsService} from '@app/services/storage/app-settings.service';
import {ClustersService} from '@app/services/storage/clusters.service';
import {ComponentsService} from '@app/services/storage/components.service';
+import {UtilsService} from '@app/services/utils.service';
@Injectable()
export class FilteringService {
- constructor(private appSettings: AppSettingsService, private clustersStorage: ClustersService, private componentsStorage: ComponentsService) {
+ constructor(private appSettings: AppSettingsService, private clustersStorage: ClustersService, private componentsStorage: ComponentsService, private utils: UtilsService) {
this.appSettings.getParameter('timeZone').subscribe(value => this.timeZone = value || this.defaultTimeZone);
this.clustersStorage.getAll().subscribe(clusters => this.filters.clusters.options = [...this.filters.clusters.options, ...clusters.map(this.getListItem)]);
this.componentsStorage.getAll().subscribe(components => this.filters.components.options = [...this.filters.components.options, ...components.map(this.getListItem)]);
@@ -41,9 +42,13 @@ export class FilteringService {
private readonly defaultTimeZone = moment.tz.guess();
+ private readonly sortMap = {
+ component_name: 'type',
+ start_time: 'logtime'
+ };
+
timeZone: string = this.defaultTimeZone;
- // TODO implement loading of real options data
filters = {
clusters: {
label: 'filter.clusters',
@@ -54,12 +59,13 @@ export class FilteringService {
}
],
selectedValue: '',
- selectedLabel: 'filter.all',
+ defaultValue: '',
+ defaultLabel: 'filter.all',
paramName: 'clusters',
},
text: {
label: 'filter.message',
- selectedValue: ''
+ defaultValue: ''
},
timeRange: {
options: [
@@ -135,18 +141,12 @@ export class FilteringService {
unit: 'h',
interval: 1
},
- selectedLabel: 'filter.timeRange.1hr'
- },
- timeZone: {
- options: moment.tz.names().map(zone => {
- // TODO map labels according to actual design requirements
- return {
- label: this.getTimeZoneLabel(zone),
- value: zone
- };
- }),
- selectedValue: this.defaultTimeZone,
- selectedLabel: this.getTimeZoneLabel(this.defaultTimeZone)
+ defaultValue: {
+ type: 'LAST',
+ unit: 'h',
+ interval: 1
+ },
+ defaultLabel: 'filter.timeRange.1hr'
},
components: {
label: 'filter.components',
@@ -158,7 +158,8 @@ export class FilteringService {
}
],
selectedValue: '',
- selectedLabel: 'filter.all'
+ defaultValue: '',
+ defaultLabel: 'filter.all'
},
levels: {
label: 'filter.levels',
@@ -198,10 +199,84 @@ export class FilteringService {
}
],
selectedValue: '',
- selectedLabel: 'filter.all'
+ defaultValue: '',
+ defaultLabel: 'filter.all'
+ },
+ sorting: {
+ label: 'sorting.title',
+ options: [
+ {
+ label: 'sorting.level.asc',
+ value: {
+ key: 'level',
+ type: 'asc'
+ }
+ },
+ {
+ label: 'sorting.level.desc',
+ value: {
+ key: 'level',
+ type: 'desc'
+ }
+ },
+ {
+ label: 'sorting.component.asc',
+ value: {
+ key: 'component_name',
+ type: 'asc'
+ }
+ },
+ {
+ label: 'sorting.component.desc',
+ value: {
+ key: 'component_name',
+ type: 'desc'
+ }
+ },
+ {
+ label: 'sorting.time.asc',
+ value: {
+ key: 'start_time',
+ type: 'asc'
+ }
+ },
+ {
+ label: 'sorting.time.desc',
+ value: {
+ key: 'start_time',
+ type: 'desc'
+ }
+ }
+ ],
+ selectedValue: '',
+ defaultValue: '',
+ defaultLabel: ''
}
};
+ timeZoneSelection = {
+ options: moment.tz.names().map(zone => {
+ // TODO map labels according to actual design requirements
+ return {
+ label: this.utils.getTimeZoneLabel(zone),
+ value: zone
+ };
+ }),
+ defaultValue: this.defaultTimeZone,
+ defaultLabel: this.utils.getTimeZoneLabel(this.defaultTimeZone)
+ };
+
+ private filtersFormItems = Object.keys(this.filters).reduce((currentObject, key) => {
+ let formControl = new FormControl(),
+ item = {
+ [key]: new FormControl()
+ };
+ formControl.setValue(this.filters[key].defaultValue);
+ return Object.assign(currentObject, item);
+ }, {});
+
+ filtersForm = new FormGroup(this.filtersFormItems);
+
readonly valueGetters = {
end_time: value => {
let time;
@@ -241,24 +316,9 @@ export class FilteringService {
}
}
return time ? time.toISOString() : '';
- }
+ },
+ sortType: value => value && value.type,
+ sortBy: value => value && (this.sortMap[value.key] || value.key)
};
- getTimeZoneLabel(timeZone) {
- return `${timeZone} (${moment.tz(timeZone).format('Z')})`;
- }
-
- valueHasChanged(currentValue: any, newValue: any): boolean {
- if (newValue == null) {
- return false;
- }
- if (typeof newValue === 'object') {
- return JSON.stringify(currentValue) !== JSON.stringify(newValue);
- } else {
- return currentValue !== newValue;
- }
- }
-
- filteringSubject = new Subject();
-
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
index 40645f0..fdebb2f 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/mock-api-data.service.ts
@@ -104,7 +104,8 @@ export class mockApiDataService implements InMemoryDbService {
const filterMapItem = this.filterMap[path];
if (query && filterMapItem) {
filteredData = {};
- const collection = allData[filterMapItem.pathToCollection],
+ const pathToCollection = filterMapItem.pathToCollection,
+ collection = allData[pathToCollection],
filteredCollection = collection.filter(item => {
let result = true;
query.paramsMap.forEach((value, key) => {
@@ -118,7 +119,24 @@ export class mockApiDataService implements InMemoryDbService {
});
return result;
});
- filteredData[filterMapItem.pathToCollection] = filteredCollection;
+ if (query.paramsMap.has('sortBy') && query.paramsMap.has('sortType')) {
+ const sortKey = query.paramsMap.get('sortBy')[0],
+ sortType = query.paramsMap.get('sortType')[0];
+ filteredCollection.sort((a, b) => {
+ const itemA = a[sortKey],
+ itemB = b[sortKey];
+ let ascResult;
+ if (itemA > itemB) {
+ ascResult = 1;
+ } else if (itemA < itemB) {
+ ascResult = -1;
+ } else {
+ ascResult = 0;
+ }
+ return ascResult * Math.pow(-1, Number(sortType === 'desc'));
+ });
+ }
+ filteredData[pathToCollection] = filteredCollection;
} else {
filteredData = allData;
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.spec.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.spec.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.spec.ts
new file mode 100644
index 0000000..a93eee5
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.spec.ts
@@ -0,0 +1,33 @@
+/**
+ * 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 {TestBed, inject} from '@angular/core/testing';
+
+import {UtilsService} from './utils.service';
+
+describe('UtilsService', () => {
+ beforeEach(() => {
+ TestBed.configureTestingModule({
+ providers: [UtilsService]
+ });
+ });
+
+ it('should create service', inject([UtilsService], (service: UtilsService) => {
+ expect(service).toBeTruthy();
+ }));
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts
new file mode 100644
index 0000000..7180ebb
--- /dev/null
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/app/services/utils.service.ts
@@ -0,0 +1,40 @@
+/**
+ * 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 {Injectable} from '@angular/core';
+import * as moment from 'moment-timezone';
+
+@Injectable()
+export class UtilsService {
+
+ valueHasChanged(currentValue: any, newValue: any): boolean {
+ if (newValue == null) {
+ return false;
+ }
+ if (typeof newValue === 'object') {
+ return JSON.stringify(currentValue) !== JSON.stringify(newValue);
+ } else {
+ return currentValue !== newValue;
+ }
+ }
+
+ getTimeZoneLabel(timeZone) {
+ return `${timeZone} (${moment.tz(timeZone).format('Z')})`;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2d5b7561/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json
----------------------------------------------------------------------
diff --git a/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json b/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json
index 755f307..33d059e 100644
--- a/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json
+++ b/ambari-logsearch/ambari-logsearch-web-new/src/assets/i18n/en.json
@@ -36,5 +36,16 @@
"levels.info": "Info",
"levels.debug": "Debug",
"levels.trace": "Trace",
- "levels.unknown": "Unknown"
+ "levels.unknown": "Unknown",
+
+ "sorting.title": "Sort By",
+ "sorting.level.asc": "Ascending Level",
+ "sorting.level.desc": "Descending Level",
+ "sorting.component.asc": "Ascending Component",
+ "sorting.component.desc": "Descending Component",
+ "sorting.time.asc": "Ascending Time",
+ "sorting.time.desc": "Descending Time",
+
+ "logs.status": "Status",
+ "logs.details": "Details"
}