Skip to content

Commit 68d5586

Browse files
Environment list search bar (#4725)
* Added search bar for Environment Signed-off-by: chaitali-mane <[email protected]> * added pagination to list Signed-off-by: chaitali-mane <[email protected]> * Updated naming convention Signed-off-by: chaitali-mane <[email protected]> * Updated pagination code Signed-off-by: chaitali-mane <[email protected]> * Added search bar for Environment Signed-off-by: chaitali-mane <[email protected]> * added pagination to list Signed-off-by: chaitali-mane <[email protected]> * Added minor style Signed-off-by: chaitali-mane <[email protected]> * removed lint errors Signed-off-by: chaitali-mane <[email protected]>
1 parent 5f0d283 commit 68d5586

File tree

9 files changed

+146
-44
lines changed

9 files changed

+146
-44
lines changed

Diff for: components/automate-ui/src/app/entities/environments/environment.action.ts

+17-4
Original file line numberDiff line numberDiff line change
@@ -11,25 +11,38 @@ export enum EnvironmentActionTypes {
1111
GET_FAILURE = 'ENVIRONMENTS::GET::FAILURE'
1212
}
1313

14-
export interface EnvironmentsSuccessPayload {
15-
environments: Environment[];
14+
export interface GetEnvironmentsPayload {
15+
environmentName: string;
16+
org_id: string;
17+
page: number;
18+
per_page: number;
19+
server_id: string;
1620
}
1721

1822
export class GetEnvironments implements Action {
1923
readonly type = EnvironmentActionTypes.GET_ALL;
20-
constructor(public payload: { server_id: string, org_id: string }) { }
24+
constructor(public payload: GetEnvironmentsPayload) { }
25+
}
26+
27+
export interface GetEnvironmentsSuccessPayload {
28+
environments: Environment[];
29+
total: number;
2130
}
2231

2332
export class GetEnvironmentsSuccess implements Action {
2433
readonly type = EnvironmentActionTypes.GET_ALL_SUCCESS;
25-
constructor(public payload: EnvironmentsSuccessPayload) { }
34+
constructor(public payload: GetEnvironmentsSuccessPayload) { }
2635
}
2736

2837
export class GetEnvironmentsFailure implements Action {
2938
readonly type = EnvironmentActionTypes.GET_ALL_FAILURE;
3039
constructor(public payload: HttpErrorResponse) { }
3140
}
3241

42+
export interface EnvironmentsSuccessPayload {
43+
environments: Environment[];
44+
}
45+
3346
export class GetEnvironment implements Action {
3447
readonly type = EnvironmentActionTypes.GET;
3548
constructor(public payload: { server_id: string, org_id: string, name: string }) { }

Diff for: components/automate-ui/src/app/entities/environments/environment.effects.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { Type } from 'app/entities/notifications/notification.model';
99
import {
1010
GetEnvironments,
1111
GetEnvironmentsSuccess,
12-
EnvironmentsSuccessPayload,
12+
GetEnvironmentsSuccessPayload,
1313
GetEnvironmentsFailure,
1414
EnvironmentActionTypes,
1515
GetEnvironment,
@@ -29,11 +29,11 @@ export class EnvironmentEffects {
2929
@Effect()
3030
getEnvironments$ = this.actions$.pipe(
3131
ofType(EnvironmentActionTypes.GET_ALL),
32-
mergeMap(({ payload: { server_id, org_id } }: GetEnvironments) =>
33-
this.requests.getEnvironments(server_id, org_id).pipe(
34-
map((resp: EnvironmentsSuccessPayload) => new GetEnvironmentsSuccess(resp)),
32+
mergeMap((action: GetEnvironments) =>
33+
this.requests.getEnvironments(action.payload).pipe(
34+
map((resp: GetEnvironmentsSuccessPayload) => new GetEnvironmentsSuccess(resp)),
3535
catchError((error: HttpErrorResponse) =>
36-
observableOf(new GetEnvironmentsFailure(error))))));
36+
observableOf(new GetEnvironmentsFailure(error))))));
3737

3838
@Effect()
3939
getEnvironmentsFailure$ = this.actions$.pipe(
@@ -42,7 +42,7 @@ export class EnvironmentEffects {
4242
const msg = payload.error.error;
4343
return new CreateNotification({
4444
type: Type.error,
45-
message: `Could not get environments: ${msg || payload.error}`
45+
message: `Could not get infra Environment details: ${msg || payload.error}`
4646
});
4747
}));
4848

Diff for: components/automate-ui/src/app/entities/environments/environment.reducer.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import { Environment } from './environment.model';
77
export interface EnvironmentEntityState extends EntityState<Environment> {
88
environmentsStatus: EntityStatus;
99
getAllStatus: EntityStatus;
10+
environmentList: {
11+
items: Environment[],
12+
total: number
13+
};
1014
}
1115

1216
const GET_ALL_STATUS = 'getAllStatus';
@@ -27,13 +31,14 @@ export function environmentEntityReducer(
2731

2832
switch (action.type) {
2933
case EnvironmentActionTypes.GET_ALL:
30-
return set(GET_ALL_STATUS, EntityStatus.loading, environmentEntityAdapter.removeAll(state));
34+
return set(GET_ALL_STATUS, EntityStatus.loading, environmentEntityAdapter
35+
.removeAll(state));
3136

3237
case EnvironmentActionTypes.GET_ALL_SUCCESS:
3338
return pipe(
34-
set(GET_ALL_STATUS, EntityStatus.loadingSuccess))
35-
(environmentEntityAdapter.setAll(action.payload.environments, state)) as
36-
EnvironmentEntityState;
39+
set('environmentList.items', action.payload.environments || []),
40+
set('environmentList.total', action.payload.total || 0)
41+
)(state) as EnvironmentEntityState;
3742

3843
case EnvironmentActionTypes.GET_ALL_FAILURE:
3944
return set(GET_ALL_STATUS, EntityStatus.loadingFailure, state);

Diff for: components/automate-ui/src/app/entities/environments/environment.requests.ts

+19-7
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,38 @@ import { Injectable } from '@angular/core';
22
import { HttpClient, HttpHeaders } from '@angular/common/http';
33
import { Observable } from 'rxjs';
44
import { environment as env } from 'environments/environment';
5-
import { EnvironmentsSuccessPayload } from './environment.action';
5+
import { GetEnvironmentsPayload } from './environment.action';
66
import { Environment } from './environment.model';
77
import { InterceptorSkipHeader } from 'app/services/http/http-client-auth.interceptor';
88

99
const headers = new HttpHeaders().set(InterceptorSkipHeader, '');
1010

11+
export interface GetEnvironmentsResponse {
12+
environments: any[];
13+
total: number;
14+
}
15+
1116
@Injectable()
1217
export class EnvironmentRequests {
1318

1419
constructor(private http: HttpClient) { }
1520

1621
// tslint:disable-next-line: max-line-length
17-
public getEnvironments(server_id: string, org_id: string):
18-
Observable<EnvironmentsSuccessPayload> {
19-
return this.http.get<EnvironmentsSuccessPayload>(
20-
`${env.infra_proxy_url}/servers/${server_id}/orgs/${org_id}/environments`, {headers});
21-
}
22-
2322
public getEnvironment(server_id: string, org_id: string, name: string): Observable<Environment> {
2423
return this.http.get<Environment>(
2524
`${env.infra_proxy_url}/servers/${server_id}/orgs/${org_id}/environments/${name}`, {headers});
2625
}
26+
27+
public getEnvironments(payload: GetEnvironmentsPayload)
28+
: Observable<GetEnvironmentsResponse> {
29+
const wildCardSearch = '*';
30+
const target = payload.environmentName !== '' ?
31+
'name:' + wildCardSearch + payload.environmentName : wildCardSearch + ':';
32+
const nameTarget = target + wildCardSearch;
33+
const currentPage = payload.page - 1;
34+
35+
const params = `search_query.q=${nameTarget}&search_query.page=${currentPage}&search_query.per_page=${payload.per_page}`;
36+
const url = `${env.infra_proxy_url}/servers/${payload.server_id}/orgs/${payload.org_id}/environments?${params}`;
37+
return this.http.get<GetEnvironmentsResponse>(url, {headers});
38+
}
2739
}

Diff for: components/automate-ui/src/app/entities/environments/environment.selectors.ts

+5
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,8 @@ export const getAllStatus = createSelector(
1616
environmentState,
1717
(state) => state.getAllStatus
1818
);
19+
20+
export const environmentList = createSelector(
21+
environmentState,
22+
(state) => state.environmentList
23+
);

Diff for: components/automate-ui/src/app/modules/infra-proxy/environments/environments.component.html

+17-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,16 @@
22
<chef-loading-spinner *ngIf="environmentsListLoading" size="50"></chef-loading-spinner>
33
<app-empty-state *ngIf="authFailure" moduleTitle="environments" (resetKeyRedirection)="resetKeyTabRedirection($event)"></app-empty-state>
44
<ng-container *ngIf="!environmentsListLoading && !authFailure">
5-
<chef-table>
5+
<div class="search-items">
6+
<app-infra-search-bar (searchButtonClick)="searchEnvironment($event)" placeHolder="environments"></app-infra-search-bar>
7+
</div>
8+
<chef-loading-spinner class="full-screen-spinner" *ngIf="searching" size="50" fixed></chef-loading-spinner>
9+
<div class="empty-section" *ngIf="!searching && !environments.length">
10+
<img alt="No preview" src="/assets/img/no_preview.gif" />
11+
<p *ngIf="searchValue != ''">No results found for "{{searchValue}}".</p>
12+
<p *ngIf="searchValue === ''">No environment available.</p>
13+
</div>
14+
<chef-table *ngIf="environments.length">
615
<chef-thead>
716
<chef-tr class="no_border_tr">
817
<chef-th class="no_border_th">Name</chef-th>
@@ -26,5 +35,12 @@
2635
</chef-tr>
2736
</chef-tbody>
2837
</chef-table>
38+
<app-page-picker
39+
class="environment-list-paging"
40+
[total]="total"
41+
[perPage]="per_page"
42+
[page]="page"
43+
(pageChanged)="onPageChange($event)">
44+
</app-page-picker>
2945
</ng-container>
3046
</section>

Diff for: components/automate-ui/src/app/modules/infra-proxy/environments/environments.component.scss

+18
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,21 @@ chef-loading-spinner {
3333
width: 100px;
3434
z-index: 199;
3535
}
36+
37+
.full-screen-spinner {
38+
display: flex;
39+
margin: auto;
40+
margin-top: 239px;
41+
background-color: #FFFFFF;
42+
opacity: 0.7;
43+
width: initial;
44+
}
45+
46+
.empty-section {
47+
margin-top: 130px;
48+
text-align: center;
49+
}
50+
51+
img {
52+
width: 70px;
53+
}

Diff for: components/automate-ui/src/app/modules/infra-proxy/environments/environments.component.ts

+54-21
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,9 @@ import { LayoutFacadeService, Sidebar } from 'app/entities/layout/layout.facade'
66
import { takeUntil } from 'rxjs/operators';
77
import { isNil } from 'lodash/fp';
88

9-
import { EntityStatus } from 'app/entities/entities';
109
import { GetEnvironments } from 'app/entities/environments/environment.action';
1110
import { Environment } from 'app/entities/environments/environment.model';
12-
import {
13-
allEnvironments,
14-
getAllStatus as getAllEnvironmentsForOrgStatus
15-
} from 'app/entities/environments/environment.selectors';
16-
11+
import { getAllStatus, environmentList } from 'app/entities/environments/environment.selectors';
1712

1813
@Component({
1914
selector: 'app-environments',
@@ -29,7 +24,13 @@ export class EnvironmentsComponent implements OnInit, OnDestroy {
2924
private isDestroyed = new Subject<boolean>();
3025
public environments: Environment[] = [];
3126
public environmentsListLoading = true;
27+
public environmentListState: { items: Environment[], total: number };
3228
public authFailure = false;
29+
public per_page = 9;
30+
public page = 1;
31+
public searching = false;
32+
public searchValue = '';
33+
public total: number;
3334

3435
constructor(
3536
private store: Store<NgrxStateAtom>,
@@ -39,29 +40,61 @@ export class EnvironmentsComponent implements OnInit, OnDestroy {
3940
ngOnInit() {
4041
this.layoutFacade.showSidebar(Sidebar.Infrastructure);
4142

42-
this.store.dispatch(new GetEnvironments({
43-
server_id: this.serverId, org_id: this.orgId
44-
}));
43+
const payload = {
44+
environmentName: '',
45+
page: this.page,
46+
per_page: this.per_page,
47+
server_id: this.serverId,
48+
org_id: this.orgId
49+
};
50+
51+
this.store.dispatch(new GetEnvironments(payload));
4552

4653
combineLatest([
47-
this.store.select(getAllEnvironmentsForOrgStatus),
48-
this.store.select(allEnvironments)
49-
]).pipe(takeUntil(this.isDestroyed))
50-
.subscribe(([ getEnvironmentsSt, allEnvironmentsState]) => {
51-
if (getEnvironmentsSt === EntityStatus.loadingSuccess && !isNil(allEnvironmentsState)) {
52-
this.environments = allEnvironmentsState;
53-
this.environmentsListLoading = false;
54-
} else if (getEnvironmentsSt === EntityStatus.loadingFailure) {
55-
this.environmentsListLoading = false;
56-
this.authFailure = true;
57-
}
58-
});
54+
this.store.select(getAllStatus),
55+
this.store.select(environmentList)
56+
]).pipe(
57+
takeUntil(this.isDestroyed))
58+
.subscribe(([_getEnvironmentsSt, EnvironmentsState]) => {
59+
if (!isNil(EnvironmentsState)) {
60+
this.environmentListState = EnvironmentsState;
61+
this.environments = EnvironmentsState?.items;
62+
this.total = EnvironmentsState?.total;
63+
this.environmentsListLoading = false;
64+
this.searching = false;
65+
}
66+
});
5967
}
6068

6169
resetKeyTabRedirection(resetLink: boolean) {
6270
this.resetKeyRedirection.emit(resetLink);
6371
}
6472

73+
searchEnvironment(currentText: string) {
74+
this.page = 1;
75+
this.searching = true;
76+
this.searchValue = currentText;
77+
this.getEnvironmentData();
78+
}
79+
80+
onPageChange(event: number): void {
81+
this.page = event;
82+
this.searching = true;
83+
this.getEnvironmentData();
84+
}
85+
86+
getEnvironmentData() {
87+
const payload = {
88+
environmentName: this.searchValue,
89+
page: this.page,
90+
per_page: this.per_page,
91+
server_id: this.serverId,
92+
org_id: this.orgId
93+
};
94+
95+
this.store.dispatch(new GetEnvironments(payload));
96+
}
97+
6598
ngOnDestroy(): void {
6699
this.isDestroyed.next(true);
67100
this.isDestroyed.complete();

Diff for: components/automate-ui/src/app/modules/infra-proxy/infra-search-bar/infra-search-bar.component.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
autocomplete="off">
1212
<button chef-button class="search-button primary" primary (click)="handleFiltersClick(search_box.value)">
1313
<chef-icon>search</chef-icon>
14-
</button>
14+
</button>
1515
</div>
1616
<ng-content></ng-content>
1717
</div>

0 commit comments

Comments
 (0)