blob: f12bff3e6a58f3955d45773928d5e8fb1d469c73 [file] [log] [blame]
/**
* 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, ViewChild, ElementRef } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { MatSort } from '@angular/material/sort';
import { MatSelectChange } from '@angular/material/select';
import { finalize, debounceTime, distinctUntilChanged } from 'rxjs/operators';
import { NgxSpinnerService } from 'ngx-spinner';
import { fromEvent } from 'rxjs';
import { SchedulerService } from '@app/services/scheduler/scheduler.service';
import { AppInfo } from '@app/models/app-info.model';
import { AllocationInfo } from '@app/models/alloc-info.model';
import { ColumnDef } from '@app/models/column-def.model';
import { CommonUtil } from '@app/utils/common.util';
import { PartitionInfo } from '@app/models/partition-info.model';
import { DropdownItem } from '@app/models/dropdown-item.model';
import { QueueInfo } from '@app/models/queue-info.model';
@Component({
selector: 'app-applications-view',
templateUrl: './apps-view.component.html',
styleUrls: ['./apps-view.component.scss'],
})
export class AppsViewComponent implements OnInit {
@ViewChild('appsViewMatPaginator', { static: true }) appPaginator!: MatPaginator;
@ViewChild('allocationMatPaginator', { static: true }) allocPaginator!: MatPaginator;
@ViewChild(MatSort, { static: true }) appSort!: MatSort;
@ViewChild('searchInput', { static: true }) searchInput!: ElementRef;
appDataSource = new MatTableDataSource<AppInfo>([]);
appColumnDef: ColumnDef[] = [];
appColumnIds: string[] = [];
allocDataSource = new MatTableDataSource<AllocationInfo>([]);
allocColumnDef: ColumnDef[] = [];
allocColumnIds: string[] = [];
selectedRow: AppInfo | null = null;
initialAppData: AppInfo[] = [];
searchText = '';
partitionList: PartitionInfo[] = [];
partitionSelected = '';
leafQueueList: DropdownItem[] = [];
leafQueueSelected = '';
constructor(
private scheduler: SchedulerService,
private spinner: NgxSpinnerService,
private activatedRoute: ActivatedRoute,
private router: Router
) {}
ngOnInit() {
this.appDataSource.paginator = this.appPaginator;
this.allocDataSource.paginator = this.allocPaginator;
this.appDataSource.sort = this.appSort;
this.appSort.sort({ id: 'submissionTime', start: 'desc', disableClear: false });
this.appColumnDef = [
{ colId: 'applicationId', colName: 'Application ID' },
{ colId: 'queueName', colName: 'Queue Name' },
{ colId: 'applicationState', colName: 'Application State' },
{
colId: 'usedResource',
colName: 'Used Resource',
colFormatter: CommonUtil.resourceColumnFormatter,
},
{ colId: 'partition', colName: 'Partition' },
{ colId: 'submissionTime', colName: 'Submission Time' },
];
this.appColumnIds = this.appColumnDef.map((col) => col.colId).concat('indicatorIcon');
this.allocColumnDef = [
{ colId: 'displayName', colName: 'Display Name' },
{ colId: 'allocationKey', colName: 'Allocation Key' },
{ colId: 'nodeId', colName: 'Node ID' },
{ colId: 'resource', colName: 'Resource', colFormatter: CommonUtil.resourceColumnFormatter },
{ colId: 'priority', colName: 'Priority' },
];
this.allocColumnIds = this.allocColumnDef.map((col) => col.colId);
fromEvent(this.searchInput.nativeElement, 'keyup')
.pipe(debounceTime(500), distinctUntilChanged())
.subscribe(() => {
this.onSearchAppData();
});
this.scheduler
.fetchPartitionList()
.pipe(
finalize(() => {
this.spinner.hide();
})
)
.subscribe((list) => {
if (list && list.length > 0) {
list.forEach((part) => {
this.partitionList.push(new PartitionInfo(part.name, part.name));
});
this.partitionSelected = list[0].name;
this.fetchQueuesForPartition(this.partitionSelected);
} else {
this.partitionList = [new PartitionInfo('-- Select --', '')];
this.partitionSelected = '';
this.leafQueueList = [new DropdownItem('-- Select --', '')];
this.leafQueueSelected = '';
this.appDataSource.data = [];
}
});
}
fetchQueuesForPartition(partitionName: string) {
this.spinner.show();
this.scheduler
.fetchSchedulerQueues(partitionName)
.pipe(
finalize(() => {
this.spinner.hide();
})
)
.subscribe((data) => {
if (data && data.rootQueue) {
const leafQueueList = this.generateLeafQueueList(data.rootQueue);
this.leafQueueList = [new DropdownItem('-- Select --', ''), ...leafQueueList];
this.leafQueueSelected = '';
this.fetchApplicationsUsingQueryParams();
} else {
this.leafQueueList = [new DropdownItem('-- Select --', '')];
}
});
}
generateLeafQueueList(rootQueue: QueueInfo, list: DropdownItem[] = []): DropdownItem[] {
if (rootQueue && rootQueue.isLeaf) {
list.push(new DropdownItem(rootQueue.queueName, rootQueue.queueName));
}
if (rootQueue && rootQueue.children) {
rootQueue.children.forEach((child) => this.generateLeafQueueList(child, list));
}
return list;
}
fetchAppListForPartitionAndQueue(partitionName: string, queueName: string) {
this.spinner.show();
this.scheduler
.fetchAppList(partitionName, queueName)
.pipe(
finalize(() => {
this.spinner.hide();
})
)
.subscribe((data) => {
this.initialAppData = data;
this.appDataSource.data = data;
});
}
fetchApplicationsUsingQueryParams() {
const partitionName = this.activatedRoute.snapshot.queryParams['partition'];
const queueName = this.activatedRoute.snapshot.queryParams['queue'];
if (partitionName && queueName) {
this.partitionSelected = partitionName;
this.leafQueueSelected = queueName;
this.fetchAppListForPartitionAndQueue(partitionName, queueName);
}
this.router.navigate([], {
queryParams: {
partition: null,
queue: null,
},
queryParamsHandling: 'merge',
});
}
unselectAllRowsButOne(row: AppInfo) {
this.appDataSource.data.map((app) => {
if (app !== row) {
app.isSelected = false;
}
});
}
toggleRowSelection(row: AppInfo) {
this.unselectAllRowsButOne(row);
if (row.isSelected) {
this.selectedRow = null;
row.isSelected = false;
this.allocDataSource.data = [];
} else {
this.selectedRow = row;
row.isSelected = true;
if (row.allocations) {
this.allocDataSource.data = row.allocations;
}
}
}
removeRowSelection() {
if (this.selectedRow) {
this.selectedRow.isSelected = false;
this.selectedRow = null;
this.allocDataSource.data = [];
}
}
onPaginatorChanged() {
this.removeRowSelection();
}
isAppDataSourceEmpty() {
return this.appDataSource.data && this.appDataSource.data.length === 0;
}
isAllocDataSourceEmpty() {
return this.allocDataSource.data && this.allocDataSource.data.length === 0;
}
onClearSearch() {
this.searchText = '';
this.removeRowSelection();
this.appDataSource.data = this.initialAppData;
}
onSearchAppData() {
const searchTerm = this.searchText.trim().toLowerCase();
if (searchTerm) {
this.removeRowSelection();
this.appDataSource.data = this.initialAppData.filter((data) =>
data.applicationId.toLowerCase().includes(searchTerm)
);
} else {
this.onClearSearch();
}
}
onPartitionSelectionChanged(selected: MatSelectChange) {
if (selected.value !== '') {
this.searchText = '';
this.partitionSelected = selected.value;
this.appDataSource.data = [];
this.removeRowSelection();
this.fetchQueuesForPartition(this.partitionSelected);
} else {
this.searchText = '';
this.partitionSelected = '';
this.leafQueueSelected = '';
this.appDataSource.data = [];
this.removeRowSelection();
}
}
onQueueSelectionChanged(selected: MatSelectChange) {
if (selected.value !== '') {
this.searchText = '';
this.leafQueueSelected = selected.value;
this.appDataSource.data = [];
this.removeRowSelection();
this.fetchAppListForPartitionAndQueue(this.partitionSelected, this.leafQueueSelected);
} else {
this.searchText = '';
this.leafQueueSelected = '';
this.appDataSource.data = [];
this.removeRowSelection();
}
}
}