/* * Copyright (C) 2024 The Android Open Source Project * * Licensed 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 {NgTemplateOutlet} from '@angular/common'; import { Component, ElementRef, EventEmitter, Inject, Input, Output, ViewChild, } from '@angular/core'; import {FormControl, Validators} from '@angular/forms'; import {assertDefined} from 'common/assert_utils'; import {Analytics} from 'logging/analytics'; @Component({ selector: 'active-search', template: ` {{label}} Enter valid SQL query.
timer Calculating results
Executed in {{lastQueryExecutionTime}}
`, styles: [ ` .header { justify-content: space-between; display: flex; align-items: center; } .query-field { height: fit-content; } .query-field textarea { height: 300px; } .query-button { width: fit-content; line-height: 24px; padding: 0 10px; } .end-align-button { align-self: end; } .query-actions { display: flex; flex-direction: row; justify-content: end; column-gap: 10px; align-items: center; } .running-query-message { display: flex; flex-direction: row; align-items: center; color: #FF8A00; } .current-search { padding: 10px 0px; } .current-search .query { display: flex; flex-direction: column; } .message-with-spinner { display: flex; flex-direction: row; align-items: center; justify-content: space-between; } `, ], }) export class ActiveSearchComponent { @Input() canClear = false; @Input() canAdd = false; @Input() isSearchInitialized = false; @Input() lastTraceFailed = false; @Input() executedQuery: string | undefined; @Input() saveQueryField: NgTemplateOutlet | undefined; @Input() label: string | undefined; @Input() lastQueryExecutionTime: string | undefined; @Input() saveQueryNameControl: FormControl | undefined; @Input() runningQuery = false; @Output() clearQueryClick = new EventEmitter(); @Output() searchQueryClick = new EventEmitter(); @Output() addQueryClick = new EventEmitter(); @ViewChild(HTMLTextAreaElement) textArea: HTMLTextAreaElement | undefined; searchQueryControl = new FormControl('', Validators.required); constructor( @Inject(ElementRef) readonly elementRef: ElementRef, ) {} updateText(text: string) { this.searchQueryControl.setValue(text); this.textArea?.focus(); } searchQueryDisabled(): boolean { return ( this.searchQueryControl.invalid || this.runningQuery || !this.isSearchInitialized ); } onTextAreaKeydown(event: KeyboardEvent) { event.stopPropagation(); if ( event.key === 'Enter' && !event.shiftKey && !this.searchQueryDisabled() ) { event.preventDefault(); this.onSearchQueryClick(); } } onSearchQueryClick() { Analytics.TraceSearch.logQueryRequested('new'); this.searchQueryClick.emit(assertDefined(this.searchQueryControl.value)); } }