1// Copyright (C) 2020 The Android Open Source Project 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15import m from 'mithril'; 16import {SimpleResizeObserver} from '../../base/resize_observer'; 17import {undoCommonChatAppReplacements} from '../../base/string_utils'; 18import {QueryResponse, runQuery} from '../../components/query_table/queries'; 19import {Callout} from '../../widgets/callout'; 20import {Editor} from '../../widgets/editor'; 21import {PageWithTraceAttrs} from '../../public/page'; 22import {QueryHistoryComponent, queryHistoryStorage} from './query_history'; 23import {Trace, TraceAttrs} from '../../public/trace'; 24import {addQueryResultsTab} from '../../components/query_table/query_result_tab'; 25import {QueryTable} from '../../components/query_table/query_table'; 26 27interface QueryPageState { 28 enteredText: string; 29 executedQuery?: string; 30 queryResult?: QueryResponse; 31 heightPx: string; 32 generation: number; 33} 34 35const state: QueryPageState = { 36 enteredText: '', 37 heightPx: '100px', 38 generation: 0, 39}; 40 41function runManualQuery(trace: Trace, query: string) { 42 state.executedQuery = query; 43 state.queryResult = undefined; 44 runQuery(undoCommonChatAppReplacements(query), trace.engine).then( 45 (resp: QueryResponse) => { 46 addQueryResultsTab( 47 trace, 48 { 49 query: query, 50 title: 'Standalone Query', 51 prefetchedResponse: resp, 52 }, 53 'analyze_page_query', 54 ); 55 // We might have started to execute another query. Ignore it in that 56 // case. 57 if (state.executedQuery !== query) { 58 return; 59 } 60 state.queryResult = resp; 61 trace.scheduleFullRedraw(); 62 }, 63 ); 64} 65 66export type QueryInputAttrs = TraceAttrs; 67 68class QueryInput implements m.ClassComponent<QueryInputAttrs> { 69 private resize?: Disposable; 70 71 oncreate({dom}: m.CVnodeDOM<QueryInputAttrs>): void { 72 this.resize = new SimpleResizeObserver(dom, () => { 73 state.heightPx = (dom as HTMLElement).style.height; 74 }); 75 (dom as HTMLElement).style.height = state.heightPx; 76 } 77 78 onremove(): void { 79 if (this.resize) { 80 this.resize[Symbol.dispose](); 81 this.resize = undefined; 82 } 83 } 84 85 view({attrs}: m.CVnode<QueryInputAttrs>) { 86 return m(Editor, { 87 generation: state.generation, 88 initialText: state.enteredText, 89 90 onExecute: (text: string) => { 91 if (!text) { 92 return; 93 } 94 queryHistoryStorage.saveQuery(text); 95 runManualQuery(attrs.trace, text); 96 }, 97 98 onUpdate: (text: string) => { 99 state.enteredText = text; 100 attrs.trace.scheduleFullRedraw(); 101 }, 102 }); 103 } 104} 105 106export class QueryPage implements m.ClassComponent<PageWithTraceAttrs> { 107 view({attrs}: m.CVnode<PageWithTraceAttrs>) { 108 return m( 109 '.query-page', 110 m(Callout, 'Enter query and press Cmd/Ctrl + Enter'), 111 state.enteredText.includes('"') && 112 m( 113 Callout, 114 {icon: 'warning'}, 115 `" (double quote) character observed in query; if this is being used to ` + 116 `define a string, please use ' (single quote) instead. Using double quotes ` + 117 `can cause subtle problems which are very hard to debug.`, 118 ), 119 m(QueryInput, attrs), 120 state.executedQuery === undefined 121 ? null 122 : m(QueryTable, { 123 trace: attrs.trace, 124 query: state.executedQuery, 125 resp: state.queryResult, 126 fillParent: false, 127 }), 128 m(QueryHistoryComponent, { 129 trace: attrs.trace, 130 runQuery: (q: string) => runManualQuery(attrs.trace, q), 131 setQuery: (q: string) => { 132 state.enteredText = q; 133 state.generation++; 134 attrs.trace.scheduleFullRedraw(); 135 }, 136 }), 137 ); 138 } 139} 140