1/** 2 * Copyright (C) 2018 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16import { Component, OnInit, ViewChild } from '@angular/core'; 17import { MatSnackBar, MatTableDataSource, PageEvent } from '@angular/material'; 18import { animate, state, style, transition, trigger } from "@angular/animations"; 19 20import { AppService } from '../../appservice'; 21import { FilterComponent } from '../../shared/filter/filter.component'; 22import { FilterItem } from '../../model/filter_item'; 23import { MenuBaseClass } from '../menu_base'; 24import { Schedule, ScheduleSuspendResponse } from '../../model/schedule'; 25import { ScheduleService } from './schedule.service'; 26 27 28/** Component that handles schedule menu. */ 29@Component({ 30 selector: 'app-schedule', 31 templateUrl: './schedule.component.html', 32 providers: [ ScheduleService ], 33 styleUrls: ['./schedule.component.scss'], 34 animations: [ 35 trigger('detailExpand', [ 36 state('void', style({height: '0px', minHeight: '0', visibility: 'hidden'})), 37 state('*', style({height: '*', visibility: 'visible'})), 38 transition('void <=> *', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')), 39 ]), 40 ], 41}) 42export class ScheduleComponent extends MenuBaseClass implements OnInit { 43 columnTitles = [ 44 '_index', 45 'test_name', 46 'device', 47 'manifest_branch', 48 'build_target', 49 'gsi_branch', 50 'gsi_build_target', 51 'test_branch', 52 'test_build_target', 53 'period', 54 'status', 55 'timestamp', 56 ]; 57 dataSource = new MatTableDataSource<Schedule>(); 58 pageEvent: PageEvent; 59 appliedFilters: FilterItem[]; 60 61 @ViewChild(FilterComponent) filterComponent: FilterComponent; 62 63 constructor(private scheduleService: ScheduleService, 64 appService: AppService, 65 snackBar: MatSnackBar) { 66 super(appService, snackBar); 67 } 68 69 ngOnInit(): void { 70 this.filterComponent.setSelectorList(Schedule); 71 this.getCount(); 72 this.getSchedules(this.pageSize, this.pageSize * this.pageIndex); 73 } 74 75 /** Gets a total count of schedules. */ 76 getCount(observer = this.getDefaultCountObservable()) { 77 const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : ''; 78 this.scheduleService.getCount(filterJSON).subscribe(observer); 79 } 80 81 /** Gets schedules. 82 * @param size A number, at most this many results will be returned. 83 * @param offset A Number of results to skip. 84 */ 85 getSchedules(size = 0, offset = 0) { 86 this.loading = true; 87 const filterJSON = (this.appliedFilters) ? JSON.stringify(this.appliedFilters) : ''; 88 this.scheduleService.getSchedules(size, offset, filterJSON, '', '') 89 .subscribe( 90 (response) => { 91 this.loading = false; 92 if (this.count >= 0) { 93 let length = 0; 94 if (response.schedules) { 95 length = response.schedules.length; 96 } 97 const total = length + offset; 98 if (response.has_next) { 99 if (length !== this.pageSize) { 100 this.showSnackbar('Received unexpected number of entities.'); 101 } else if (this.count <= total) { 102 this.getCount(); 103 } 104 } else { 105 if (this.count !== total) { 106 if (length !== this.count) { 107 this.getCount(); 108 } else if (this.count > total) { 109 const countObservable = this.getDefaultCountObservable([ 110 () => { 111 this.pageIndex = Math.floor(this.count / this.pageSize); 112 this.getSchedules(this.pageSize, this.pageSize * this.pageIndex); 113 } 114 ]); 115 this.getCount(countObservable); 116 } 117 } 118 } 119 } 120 this.dataSource.data = response.schedules; 121 }, 122 (error) => this.showSnackbar(`[${error.status}] ${error.name}`) 123 ); 124 } 125 126 /** Toggles a schedule from suspend to resume, or vice versa. */ 127 suspendSchedule(schedules: ScheduleSuspendResponse[]) { 128 this.scheduleService.suspendSchedule(schedules) 129 .subscribe( 130 (response) => { 131 if (response.schedules) { 132 let self = this; 133 response.schedules.forEach(function(schedule) { 134 const original = self.dataSource.data.filter(x => x.urlsafe_key === schedule.urlsafe_key); 135 if (original) { 136 original[0].suspended = schedule.suspend; 137 } 138 }) 139 } 140 }, 141 (error) => this.showSnackbar(`[${error.status}] ${error.name}`) 142 ); 143 } 144 145 /** Hooks a page event and handles properly. */ 146 onPageEvent(event: PageEvent) { 147 this.pageSize = event.pageSize; 148 this.pageIndex = event.pageIndex; 149 this.getSchedules(this.pageSize, this.pageSize * this.pageIndex); 150 return event; 151 } 152 153 /** Applies a filter and get entities with it. */ 154 applyFilters(filters) { 155 this.pageIndex = 0; 156 this.appliedFilters = filters; 157 this.getCount(); 158 this.getSchedules(this.pageSize, this.pageSize * this.pageIndex); 159 } 160} 161